在Bash/Linux中查找.txt文件中的非ASCII字符并用ASCII字符替换它。

3

我有一份从海洋仪器卸载下来的文件列表。由于某些原因,偶尔会在应该是ASCII字符的地方插入非ASCII字符。我发现在经度记录中应该用W表示西半球时,出现了grave-E(È)。

以下是数据的样式:

CUMSECS Date UTC    Time UTC    Date Local  Time local  Z (m)   Target Z    Z Bot   Temp    PAR Salin   Ang VelX    Ang VelY    Ang VelZ    Pump +  Pump -  Gctr    Fix secs    Date UTC    Time UTC    Date Local  Time Local  Lat LatD    Latm        Lon LonD    Lonm        DOP Temp    PAR Salin   Batt V      CMD secs    Date Local  Time Local  No. Cmds
526068034   09/01/16    18:00:34    09/01/16    11:00:34     3.75    2.69    
3.75     0.29    0.000000    0.00   -12 -70 -50 0   5   10
526068039   09/01/16    18:00:39    09/01/16    11:00:39     3.75    2.69    
3.75     0.29    0.000000    0.00   -12 -70 -50 0   5   10
526068044   09/01/16    18:00:44    09/01/16    11:00:44     3.74    2.69    
3.75     0.29    0.000000    0.00   -12 -70 -50 0   5   10
526068049   09/01/16    18:00:49    09/01/16    11:00:49     3.73    2.69    
3.75     0.29    0.000000    0.00   -30732  13588   31909   60399   7538    -82
543622771   03/23/17    22:19:31    03/23/17    15:19:31    38.31877    38  
19.1262 N   123.07136   123  4.2812 È   23.6    115.06     0.0000   96.00   
121.718 
547764151   05/10/17    20:42:31    05/10/17    13:42:31     0.03   16.00   
127.00  13.68   1074.904320 33.56   -4908   -3976   261 1   0   0
547764152   05/10/17    20:42:32    05/10/17    13:42:32     0.00   16.00   
127.00  13.68   1074.904320 33.56   -4908   -3976   261 1   0   0

我可以使用以下Bash命令找到非ASCII字符: pcregrep -n '[^\x00-\x7F]' 170510_ocean_Copepod.txt 我想循环处理一系列文件,查找这些字符,并将它们替换为“W”,以便随后批量读取并处理这些文件。或者,解决R在尝试读取这些文件时返回的错误("multibyte string in location..."),也同样可行。非常感谢您的帮助。

pcregrep -n '[^\x00-\x7F]' 170510_ocean_Copepod.txt | sed 's/[^\x00-\x7F]/W/g',但在sed调用中返回一个非法字节序列的错误。 - Connor Dibble
你尝试过更改read.table函数中的fileEncoding参数吗? - Scarabee
我已经尝试了R中的fileEncoding和Encoding路线(明确调用它的latin1或utf8),但都没有成功。我对编码问题的理解可能有限,但据我所知,这不是真正的编码问题。也许我错了- 有什么想法吗? - Connor Dibble
3
这段命令的意思是:将 <file> 文件中的所有字符 'È' 替换为 'W',然后通过标准输出打印出来。 - Jack
所以我从来没有成功地使用tr方法,它总是返回一个"error: illegal byte sequence"的错误。但是,我按照Kind Stranger建议的方式使用了iconv,这是成功的。最终,我没有替换字符,但我能够让编码被R识别,以便我可以批量处理那些隐藏的小多字节字符的文件。如果有人有任何关于如何实际替换字符(或者为什么我在MacOSX bash终端会话中遇到这样的错误)的想法,那将帮助我使代码更加健壮。目前,我的研究仍停留在一个半球。 - Connor Dibble
2个回答

2

我认为问题在于utf-8中的È是一个由\xc3\x88组成的多字节字符,而sed似乎无法处理这个问题。正如@Jack建议的那样,在没有pcregrep的Windows bash中,tr可能是更好的工具:

user@PC:~$ grep -P '[^\x00-\x7f]' | tr 'È' 'W'
19.1262 N   123.07136   123  4.2812 WW   23.6    115.06     0.0000   96.00

请注意它确实将两个字节分别转换为W

另一种方法是使用iconv将整个文件进行转换。 iso-8859-15(拉丁-9)是单字节字符编码的一个例子。 使用iconv转换文件的命令如下:

iconv -f utf-8 -t iso-8859-15 -o <converted-file> <input-file>

1
另一个选择可能是在使用 r 读取文件之前使用 iconv 转换文件编码。 - Kind Stranger
看起来使用 tr 的 shell 方法会起作用,但我也很好奇编码是什么。你知道我可以转换成哪种编码,不包含任何多字节字符,并且可以随后读入 R 吗?感谢你的有用建议。 - Connor Dibble
看起来 tr 方法也挂了。无论是使用“cat <file> |tr 'È' 'W'”还是“pcregrep -n '[^\x00-\x7F]' 170510_ocean_Copepod.txt | tr 'È' 'W'”,我都会收到错误:“tr: Illegal byte sequence”。如果我使用 cat 方法,它会将 È 所在的行打印出来,然后返回错误信息。 - Connor Dibble
@SeaSpider,已经添加了有关iconv的详细信息。 - Kind Stranger

0

你可以使用 sed 命令将 È 替换为 W

sed 's/È/W/g' 170510_ocean_Copepod.txt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接