只有在条件适用的情况下删除非ASCII字符,在bash中
问题描述:
我有一个非常特殊的需求,为此我一直试图解决,但没有成功。只有在条件适用的情况下删除非ASCII字符,在bash中
我有一个日志,它是由一个tcp/ip套接字转储创建的......它将十六进制转换为ASCII,但自然也有一些特殊字符。
我已经设法删除它们,但是我目前遇到了一些困难:有时,发送了一个0x0A,这与我的应用程序混淆了......我试图将其删除,但它也删除了在该行的末尾有效的0x0A ...
基本上,我有,在日志文件:
08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={
Teste String2}
08-14-2017 10:00:00 String={
Teste String3}
08-14-2017 10:00:00 String={Teste String4}
我想最终结果为
08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={Teste String2}
08-14-2017 10:00:00 String={Teste String3}
08-14-2017 10:00:00 String={Teste String4}
中的人物总是之间{},所以}之后的每个0x0A都是有效的,但里面不是。
我试过的每一个命令要么删除所有的0x0A,要么根本不工作。
我试过的东西
sed 's/^[^}]*}//'
sed 's/\x0A$//'
有什么想法?
答
这当然是可能的SED,但它更容易阅读和理解AWK:
awk 'BEGIN{ OFS=FS="{"; ORS=RS="}" } { sub(/[^[:print:]]/,"",$2) } 1' input.txt
这是什么呢?
- 首先,我们设定的输入和输出字段分隔符来
{
,我们的输入和输出的记录分隔符来}
。这让我们可以预测地将括号内的文字作为特定的字段(至少根据您的样本数据)。 - 接下来,我们用一个空字符串替换字段#2中的所有非打印字符,从而消除换行符,退格等。
- 最后,我们使用awk速记打印行。
答
使用sed:
的Linux:
$ sed -r ':a;N;$!ba;s/(\{[^}]*)\\n([^{]*\})/\1\2/g' file
08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={Teste String2}
08-14-2017 10:00:00 String={Teste String3}
08-14-2017 10:00:00 String={Teste String4}
的FreeBSD和MacOS:
sed -e ':a' -e 'N;$!ba' -e 's/(\{[^}]*)\\n([^{]*\})/\1\2/g' file
说明
-e ':a' -e 'N;$!ba'
允许我们在sed的每次迭代中考虑当前行和下一行。有关详细信息,请参阅this SO answer。
(\{[^}]*)
确保有一个开口支架,紧随其后的是一个开口支架。
([^{]*\})
正好相反。
答
的Perl:
$ perl -0777 -pe 's/({[^}]*)\x0A([^}]*})/\1\2/g' file
08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={Teste String2}
08-14-2017 10:00:00 String={Teste String3}
08-14-2017 10:00:00 String={Teste String4}
纯击(基于anubhava的AWK):
while IFS="\n" read -r line; do
le=""
[[ $line =~ \} ]] && le=$'\n'
printf "%s%s" "$line" "$le"
done <file
答
另一个简单awk
:
awk '{printf "%s%s", $0, (/}/ ? ORS : "")}' file
08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={Teste String2}
08-14-2017 10:00:00 String={Teste String3}
08-14-2017 10:00:00 String={Teste String4}
此awk
命令检查存在在一行中,然后只打印换行符,否则打印记录不换行。
答
随着GNU AWK多焦RS我们就可以隔离每个{...}
串并删除新行内它:
$ awk -v RS='{[^}]+}' '{ORS=gensub(/\n/,"","g",RT)}1' file
08-14-2017 10:00:00 String={Teste String}
08-14-2017 10:00:00 String={Teste String2}
08-14-2017 10:00:00 String={Teste String3}
08-14-2017 10:00:00 String={Teste String4}
对于这个特定的情况下,其他的awk答案会工作得很好,上面只是一个更通用的解决方案来隔离分隔字符串,然后在其上执行操作(如在此情况下删除字符)。
你在ASCII文本或十六进制上应用sed命令吗? – pchaigno
关于ASCII文本... –