我想從每行中刪除第一個字元作為其特殊字元並將文件轉換為 ;分號分隔的文件

我想從每行中刪除第一個字元作為其特殊字元並將文件轉換為 ;分號分隔的文件

原始檔在每一行的開頭都有一個特殊字元。文件以雙空格分隔。

樣本資料檔:

â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 語言環境的字元)。

相關內容