Awk
修剪 CSV 文件中的路徑名
我正在為一個過濾器苦苦掙扎,在該過濾器中,我試圖在第 3 次或第 n 次出現字元後修剪 CSV 的特定列中的數據
\
。我的數據看起來像這樣:
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data data,data,c:\path1\folder2\folder3\folder4\...,data,data,data data,data,c:\path1\folder2\folder3\folder4\...,data,data,data data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
我希望過濾器產生:
data,data,c:\path1\folder2\folder3\,data,data,data
第 3 列包含文件路徑,它可能位於從一個文件夾到多個文件夾的任何位置。我希望最多有 3 個文件夾。
我不想刪除其他剩餘的列,但要編輯文件。
我一直在嘗試使用
awk
,sed
並嘗試將cut
命令組合cut -f1-4 -d '\'
成一個awk
語句,但我一生都無法讓它發揮作用。
使用 GNU awk 進行 gensub():
$ awk -v n=3 'BEGIN{FS=OFS=","} {$3=gensub("(([^\\\\]*\\\\){"n+1"}).*","\\1",1,$3)} 1' file data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data
或使用任何 awk:
$ awk -v n=3 'BEGIN{FS=OFS=","} match($3,"(([^\\\\]*\\\\){"n+1"})"){$3=substr($3,1,RLENGTH)} 1' file data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data
使用
sed
,假設沒有其他更早的欄位包含由四個反斜杠分隔的字元串:$ sed 's/\(\([^,\]\{1,\}[\]\)\{4\}\)[^,]*/\1/' file data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data
或者,使用擴展的正則表達式,
$ sed -E 's/(([^,\]+[\]){4})[^,]*/\1/' file data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data data,data,c:\path1\folder2\folder3\,data,data,data
這裡使用的
sed
表達式是一個替換,被替換的文本是任何匹配的內容(([^,\]+[\]){4})[^,]*
。此正則表達式匹配並擷取四個以反斜杠分隔的非空字元串 (([^,\]+[\]){4}
)。這被擷取以在替換字元串中重複使用,但是直到並包括下一個逗號(與尾隨匹配的任何內容[^,]*
)的所有內容都將被丟棄。替換文本是
\1
,它插入這四位反斜杠分隔的字元串。您顯然也可以這樣做
cut
,paste
但請注意,以下命令管道會讀取文件三次,並且還會在第三個欄位的路徑名上刪除最後的反斜杠:$ paste -d , <( cut -d , -f -2 file ) <( cut -d , -f 3 file | cut -d '\' -f -4 ) <( cut -d , -f 5- file ) data,data,c:\path1\folder2\folder3,data,data data,data,c:\path1\folder2\folder3,data,data data,data,c:\path1\folder2\folder3,data,data data,data,c:\path1\folder2\folder3,data,data
您可以通過將前兩個欄位視為第三個欄位中路徑名的一部分來擺脫第
cut
一個欄位,但這仍然會讀取文件兩次:$ paste -d , <( cut -d '\' -f -4 file ) <( cut -d , -f 5- file ) data,data,c:\path1\folder2\folder3,data,data data,data,c:\path1\folder2\folder3,data,data data,data,c:\path1\folder2\folder3,data,data data,data,c:\path1\folder2\folder3,data,data