
原始檔在每一行的開頭都有一個特殊字元。文件以雙空格分隔。
樣本資料檔:
âNAME ABC
âAGE 21
âADDRESS XYZ street ABC city
âCONTACT 13244235
âDOJ 20181212
我想刪除â
每行中的第一個特殊字符,並將檔案轉換為;
(分號)分隔的檔案。
我編寫的以下程式碼在 UAT 中運作正常,但在 PROD 中無法正常運作:
awk '{ print substr($0,1) }' FILE1.txt | sed 's/ /;/' > FILE2.txt
UAT輸出(預期的期望輸出):
NAME;ABC
AGE;21
ADDRESS;XYZ street ABC city
CONTACT;13244235
DOJ;20181212
產品輸出:
âNAME;ABC
âAGE;21
âADDRESS;XYZ street ABC city
âCONTACT;13244235
âDOJ;20181212
相同的程式碼在 UAT 中運作正常,即刪除第一個字元並將檔案轉換為;
分號分隔,但在 PROD 中它不會刪除第一個特殊字符,而是將檔案轉換為分號分隔。
輸出locale
:
locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
誰能幫我解決這個問題..?
答案1
我認為你的問題可能是連結到字元編碼,嘗試FILE1.txt
在兩個環境中顯示
hexdump -C FILE1.txt
它可以編碼為 E-ascii 或 UTF-8(請參閱https://en.wikipedia.org/wiki/%C3%82#Character_mappings)
要解決您的問題,您可以嘗試匹配兩種編碼:
â in UTF-8 â in other encoding
| |
v v
sed 's/\xc3\xa2//' FILE1.txt | sed 's/\xE2//' > FILE2.txt
另一種解決方案可能是在處理文件之前將文件轉換為已知編碼。
不測試 PROD 編碼可能會很危險。
答案2
由於â
您看到的幾乎肯定是編碼問題,並且假設所有行都應該以大寫字母開頭,因此您可以嘗試以下操作:
LC_ALL=C sed 's/^[^A-Z]*//; s/ */;/g' FILE1.txt > FILE2
這將使用區域設定運行命令,C
該區域設定應確保您的任何字元â
都不包含在 AZ 範圍內。然後,sed 命令簡單地從每行開頭刪除所有不在 AZ 範圍內的字符,然後將所有出現的兩個或多個空格轉換為;
.
答案3
嘗試
sed 's/^â//; s/ */;/g' FILE1.txt > FILE2.txt
如果它不適合你,請投反對票
答案4
要刪除每行的第一個字符,應該是:
cut -c2- # not with the GNU implementation which is currently not multi-byte aware
sed 's/^.//'
awk '{print substr($0, 2)}' # note the 2 instead of 1 as offsets are 1-based
# not with mawk or other non-multi-byte aware awk
# implementations.
但請注意,為了.
匹配該â
字元並substr()
正常工作,â
必須根據區域設定的編碼對其進行編碼(請參閱 的輸出locale charmap
)。
若要刪除第一個字元並將所有空白序列替換為;
,您可以執行以下操作:
sed 's/^.//;s/[[:space:]]\{1,\}/;/g'
或者:
awk -v OFS=';' '{$0 = substr($0, 2); $1 = $1; print}'
(但請注意,後者不會包含;
以空白字元結尾的行的尾隨,並且被視為分隔符號的空白字元清單因awk
實現和區域設定而異)。
現在,也要注意â
(U+00E2) 在 iso8859-1 字元集(也稱為latin1
和其他一些單字節字元集)中被編碼為位元組 0xe2。而那個位元組 0xe2 也剛好是多個 3 位元組 UTF-8 字元編碼的第一個位元組,其中有幾個 Unicode 空白字元(如 U+2000 到 U+200B 空格字元)。
因此,如果您在 latin1 終端中看到â
顯示,則輸入實際上可能包含 U+2002 (EN SPACE),例如以 UTF-8 (0xe2 0x80 0x82) 編碼,並且您的終端會將其顯示0xe2
為â
和不會顯示任何不在latin1 中的0x80 和0x82。
要擺脫 EN SPACE,您需要剝離 1 個字元作為 UTF-8 語言環境,或剝離 3 個單字節語言環境字元(例如使用 latin1 或 C 語言環境的字元)。