用sed跳过/删除非ascii字符

时间:2011-12-20 06:34:21

标签: sed

  

Chip,Dirkland,DrobæSphereInc,cdirkland @ hotmail.com,usa

我一直在尝试使用sed来修改.csv中的电子邮件地址,但上面的一行仍然让我沮丧,使用如下命令:

sed -i 's/[\d128-\d255]//' FILENAME

from this stackoverflow question

似乎不起作用,因为我收到'无效的校对字符'错误。

理想情况下,我根本不想改变组合的AE角色,我宁愿只是跳过它,因为我不是试图操纵那个文本而是操纵电子邮件地址。只要那个AE在那里虽然它导致我的sed替换在一行之后失败,但删除该字符并且它处理整个文件。

有什么想法吗?

6 个答案:

答案 0 :(得分:5)

sed -i 's/[^[:print:]]//' FILENAME

此外,这就像dos2unix

答案 1 :(得分:4)

这可能适合你(GNU sed):

echo "Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa" |
sed 's/\o346/a+e/g'
Chip,Dirkland,Droba+eSphere Inc,cdirkland@hotmail.com,usa

然后做你必须做的事情,然后恢复do:

echo "Chip,Dirkland,Droba+eSphere Inc,cdirkland@hotmail.com,usa" | 
sed 's/a+e/\o346/g'
Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa

如果您在字符串中有棘手的字符,并想了解sed如何看待它们,请使用l0命令(请参阅here)。对于调试困难的正则表达式也非常有用。

echo "Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa" | 
sed -n 'l0'
Chip,Dirkland,Drob\346Sphere Inc,cdirkland@hotmail.com,usa$

答案 2 :(得分:1)

我来到这里尝试这个sed命令s/[\x00-\x1F]/ /g;,它给了我同样的错误信息。

在这种情况下,只需从排序规则中删除\x00即可,产生s/[\x01-\x1F]/ /g;

不幸的是,似乎所有上面的字符,包括\x7F和其他一些字符都是不允许的,正如这个简短的脚本所示:

for (( i=0; i<=255; i++ )); do 
    printf "== $i - \x$(echo "ibase=10;obase=16;$i" | bc) =="
    echo '' | sed -E "s/[\d$i-\d$((i+1))]]//g"
done

请注意,问题只是使用这些字符来指定范围。您仍然可以手动或按脚本列出所有内容。例如。回到你的榜样:

sed -i 's/[\d128-\d255]//' FILENAME

会变成

c=; for (( i=128; i<255; i++ )); do c="$c\d$i"; done
sed -i 's/['"$c"']//' FILENAME

将转换为:

sed -i 's/[\d128\d129\d130\d131\d132\d133\d134\d135\d136\d137\d138\d139\d140\d141\d142\d143\d144\d145\d146\d147\d148\d149\d150\d151\d152\d153\d154\d155\d156\d157\d158\d159\d160\d161\d162\d163\d164\d165\d166\d167\d168\d169\d170\d171\d172\d173\d174\d175\d176\d177\d178\d179\d180\d181\d182\d183\d184\d185\d186\d187\d188\d189\d190\d191\d192\d193\d194\d195\d196\d197\d198\d199\d200\d201\d202\d203\d204\d205\d206\d207\d208\d209\d210\d211\d212\d213\d214\d215\d216\d217\d218\d219\d220\d221\d222\d223\d224\d225\d226\d227\d228\d229\d230\d231\d232\d233\d234\d235\d236\d237\d238\d239\d240\d241\d242\d243\d244\d245\d246\d247\d248\d249\d250\d251\d252\d253\d254\d255]//' FILENAME

答案 3 :(得分:1)

您遇到的问题是本地问题。

如果要使用类似的排序规则范围,则需要更改字符类型和排序规则类型。

此操作失败,因为\ x80-> \ xff在utf-8字符串中无效。 注意\ u0080!= \ x80表示utf8。

反正要让它正常工作

LC_ALL=C sed -i 's/[\d128-\d255]//' FILENAME

这将覆盖一个命令的LC_CTYPE和LC_COLLATE并执行您想要的操作。

答案 4 :(得分:0)

如何使用awk来实现此目的。我们将Field Separator设置为空。然后遍历每个字符。使用if loop检查它是否与我们的character class匹配。如果我们打印它,否则我们会忽略它。

awk -v FS="" '{for(i=1;i<=NF;i++) if($i ~ /[A-Za-z,.@ ]/) printf $i}'

<强>测试

[jaypal:~/Temp] echo "Chip,Dirkland,DrobæSphere Inc,cdirkland@hotmail.com,usa" | 
awk -v FS="" '{for(i=1;i<=NF;i++) if($i ~ /[A-Za-z,.@ ]/) printf $i}'
Chip,Dirkland,DrobSphere Inc,cdirkland@hotmail.com,usa

<强>更新

awk -v FS="" '{for(i=1;i<=NF;i++) if($i ~ /[A-Za-z,.@ ]/) printf $i; printf "\n"}' < datafile.csv > asciidata.csv

我在循环后添加了printf“\ n”以保持行分开。

答案 5 :(得分:0)

在这种情况下,有一种方法可以跳过非ASCII字符,而不用去除。

LANG=C sed /someemailpattern/

请参阅https://bugzilla.redhat.com/show_bug.cgi?id=440419Will sed (and others) corrupt non-ASCII files?