我有一些巨大的檔案,其值由豎線 (|) 符號分隔。我們參考的字串,但有時在參考的字串之間有換行符。
我需要使用 oracle 的外部表讀取這些檔案,但在換行符上他會給我錯誤。所以我需要用空格替換它們。
我對這些檔案執行了其他一些 perl 命令來解決其他錯誤,所以我想在單行 perl 命令中找到解決方案。
我在 stackoverflow 上發現了一些其他類似的問題,但它們的作用并不完全一樣,而且我無法通過那里提到的解決方案找到解決問題的方法。
我嘗試過但不起作用的宣告:
perl -pi -e 's/"(^|)*\n(^|)*"/ /g' test.txt
示范文本:
4454|"test string"|20-05-1999|"test 2nd string"
4455|"test newline
in string"||"test another 2nd string"
4456|"another string"|19-03-2021|"here also a newline
"
4457|.....
應該變成:
4454|"test string"|20-05-1999|"test 2nd string"
4455|"test newline in string"||"test another 2nd string"
4456|"another string"|19-03-2021|"here also a newline "
4457|.....
uj5u.com熱心網友回復:
聽起來你想要一個 CSV 決議器,比如Text::CSV_XS(通過你的作業系統的包管理器或最喜歡的 CPAN 客戶端安裝):
$ perl -MText::CSV_XS -e '
my $csv = Text::CSV_XS->new({sep => "|", binary => 1});
while (my $row = $csv->getline(*ARGV)) {
$csv->say(*STDOUT, [ map { tr/\n/ /r } @$row ])
}' test.txt
4454|"test string"|20-05-1999|"test 2nd string"
4455|"test newline in string"||"test another 2nd string"
4456|"another string"|19-03-2021|"here also a newline "
這個單行程式使用|欄位分隔符而不是普通逗號讀取每個記錄,并且對于每個欄位,用空格替換換行符,然后列印出轉換后的記錄。
uj5u.com熱心網友回復:
在您的特定情況下,您還可以考慮使用 GNU 的解決方法sed或者awk.
一個awk命令看起來像
awk 'NR==1 {print;next;} /^[0-9]{4,}\|/{print "\n" $0;next;}1' ORS="" file > newfile
ORS(輸出記錄分隔符)設定為空字串,這意味著\n僅在以 4 位或更多數字開頭后跟|char(與^[0-9]{4,}\|POSIX ERE 模式匹配)開頭的行之前添加。
GNUsed命令看起來像
sed -i ':a;$!{N;/\n[0-9]\{4,\}|/!{s/\n/ /;ba}};P;D' file
這會將兩行連續的行讀入模式空間,一旦第二行不是以四位數字開頭,后跟一個|字符(參見[0-9]\{4\}|POSIX BRE 正則運算式模式),兩者之間的或多個換行符將替換為空格。重復搜索和替換,直到沒有匹配或檔案結尾。
和perl, 如果檔案很大但它仍然可以放入記憶體中, 你可以使用一個短的
perl -0777 -pi -e 's/\R (?!\d{4,}\|)/ /g' <<< "$s"
使用-0777,您可以對檔案進行 slurp,并且該\R (?!\d{4,}\|)模式匹配任何一個或多個換行符 ( \R ),而不是后跟四個或更多數字后跟一個|字符。 所有格量詞需要進行負前瞻以(?!...)禁止回溯到換行匹配模式。
uj5u.com熱心網友回復:
使用您顯示的示例,這可以簡單地在awk程式中完成。用 GNU 撰寫和測驗awk,應該可以在任何awk. 即使在大檔案上也應該可以快速作業(比將整個檔案吞入記憶體更好,提到 OP 可能會在大檔案上使用它)。
awk 'gsub(/"/,"&")%2!=0{if(val==""){val=$0} else{print val $0;val=""};next} 1' Input_file
說明:為上述添加詳細說明。
awk ' ##Starting awk program from here.
gsub(/"/,"&")%2!=0{ ##Checking condition if number of " are EVEN or not, because if they are NOT even then it means they are NOT closed properly.
if(val==""){ val=$0 } ##Checking condition if val is NULL then set val to current line.
else {print val $0;val=""} ##Else(if val NOT NULL) then print val current line and nullify val here.
next ##next will skip further statements from here.
}
1 ##In case number of " are EVEN in any line it will skip above condition(gusb one) and simply print the line.
' Input_file ##Mentioning Input_file name here.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/425568.html
