我想从每行中删除第一个字符作为其特殊字符并将文件转换为;分号分隔的文件

我想从每行中删除第一个字符作为其特殊字符并将文件转换为;分号分隔的文件

源文件在每一行的开头都有一个特殊字符。文件以双空格分隔。

样本数据文件:

â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 语言环境的字符)。

相关内容