使用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,后跟单引号时如何匹配反斜杠字符(是的,这是两个字符)的主要内容,如果未能解决你的问题,请参考以下文章

关于js怎样替换反斜杠和单引号的问题

linux命令学习-引用符号(反斜杠,单引号'',双引号"")

每日linux命令学习-引用符号(反斜杠,单引号'',双引号"")

单引号字符串与双引号字符串中的反斜杠

单引号是不是将反斜杠视为 bash 脚本中的特殊字符?

shell中单引号双引号反斜杠简说