使用awk,后跟单引号时如何匹配反斜杠字符(是的,这是两个字符)
Posted
技术标签:
【中文标题】使用awk,后跟单引号时如何匹配反斜杠字符(是的,这是两个字符)【英文标题】:With awk, how to match the backslash character when followed by single quote (yes that is two characters) 【发布时间】:2021-12-06 01:15:56 【问题描述】:我有一个由我无法控制的自动化过程定期生成的日志文件。在这个日志文件中有很多反斜杠字符(不是“转义”)的实例,后面紧跟一个单引号\'
。因此它是一个两个字符的文本模式。
我正在寻找 awk 或 sed 示例,它们将匹配两个字符 \'
模式,并将其替换为单引号 '
的单字符模式。在我的环境中,我仅限于 bash 和标准 gnu-utils; python 或 perl 等花哨的东西不适用于解决此问题的目标环境。
我尝试过:
cat F1.log | awk 'gsub(/\\t/,"\t")1' | awk 'gsub(/\\'/,"\'")1' > F2.log
cat F1.log | awk 'gsub(/\\t/,"\t")1' | sed 's/$(echo "\134\047")/$(echo \047")/g' > F2.log
旁注:第一个内联 awk 一直是一个长期有效的工具,用于将 \t
实例的两个字符模式匹配/转换为单个字符 t
。我只是为同一命令添加了一个新的内联 awk 实例,并将 t
替换为 '
,但结果在语法上不正确。
对于第一个,错误是:-bash: syntax error near unexpected token `)'
对于第2个,错误是:sed: -e expression #1, char 36: Invalid back reference
这是最近日志文件中的一个实例,其中有一条适当的数据行通过管道传输到od -bc
:
0000000 040 040 040 040 040 040 040 040 040 040 040 040 040 040 040 147
g
0000020 160 147 072 040 153 145 171 142 157 170 040 134 047 057 164 155
p g : k e y b o x \ ' / t m
0000040 160 057 056 147 156 165 160 147 057 160 165 142 162 151 156 147
p / . g n u p g / p u b r i n g
我知道单引号/双引号和/或括号有问题。我先广泛搜索了 ***,然后搜索了谷歌,但没有找到任何解决方案。
非常感谢您的帮助,谢谢。
【问题讨论】:
您是否只需要在t
和'
之前删除\,或者如果将所有\ 都删除,结果就可以了吗?
【参考方案1】:
你不能用单引号做同样的事情的原因是你的脚本是用单引号写的:
awk 'gsub(/\\'/,"\t")1'
# ^ ^ ^
# | ??? End of string
# Start of string
您需要使用以下模式之一来转义单引号:
'stringA'"'"'stringB'
'stringA'\''stringB'
或者您可以在模式和替换中键入单引号的八进制代码:
awk 'gsub(/\\\047/,"\047")1'
将它们粘合在一起,我们得到:
awk '
gsub(/\\t/,"\t")
gsub(/\\\047/,"\047")
1
' F1.log > F2.log
需要考虑的两件事:
-
首先为什么您的数据会“损坏”?
是否也应该添加对所有其他转义序列的支持?
【讨论】:
【参考方案2】:试试
gawk -c/mawk/nawk 'gsub(/[\134][\047]/,"\f")+1'
gawk (any mode other than -c) 'gsub(/[\\][\047]/,"\f")+1'
原因是 gawk 的默认正则表达式引擎的行为相当不同。我已经讨论了一些关于正则表达式如何出错的不同变体:
gawk -e ' print a="\011left]\134\47right" '
left]\'right
--[ CORRECT ]-----------------------------------
sub(/\\\47/,"\f", a)
sub(/\\[\47]/,"\f", a)
sub(/[\\][\47]/,"\f", a)
sub(/[\\134][\47]/,"\f", a)
left]
right
--[ MATCHED WRONG CHAR ]----------------------------
sub(/[\134][\47]/,"\f", a)
left
\'right
--[ ERRORED OUT ]—————————————————
sub(/\\\\\134\\47/,"\f", a)
gawk: cmd. line:1: error: Invalid back reference: /\\\\\\\47/
sub(/\\\134\\47/,"\f", a)
gawk: cmd. line:1: error: Invalid back reference: /\\\\\47/
sub(/[\134]\47/,"\f", a)
gawk: cmd. line:1: error: Unmatched [, [^, [:, [., or [=: /[\]'/
--[ NOTHING MATCHED ]-----------------------------------
sub(/\\\[\47]/,"\f", a)
sub(/\\\\[\47]/,"\f", a)
sub(/\\\\\\47/,"\f", a)
sub(/\\\\\134[\47]/,"\f", a)
sub(/\\\\\134\47/,"\f", a)
sub(/\\\\\47/,"\f", a)
sub(/\\\\134[\47]/,"\f", a)
sub(/\\\\134\\47/,"\f", a)
sub(/\\\\134\47/,"\f", a)
sub(/\\\\47/,"\f", a)
sub(/\\\134[\47]/,"\f", a)
sub(/\\\134\47/,"\f", a)
sub(/\\134[\47]/,"\f", a)
sub(/\\134\\47/,"\f", a)
sub(/\\134\47/,"\f", a)
sub(/\134\47/,"\f", a)
left]\'right
【讨论】:
【参考方案3】:我在这里找到了相关答案:How would I replace a single quote (') with a backslash then single quote (\') using sed?
主要答案的倒数起到了作用。
sed s/"\\\'"/\'/g
【讨论】:
不要这样做,它使用的所有引号都不正确,并且缺少脚本分隔符引号。以上是关于使用awk,后跟单引号时如何匹配反斜杠字符(是的,这是两个字符)的主要内容,如果未能解决你的问题,请参考以下文章
linux命令学习-引用符号(反斜杠,单引号'',双引号"")