使用反斜杠或单引号进行字段分隔

使用反斜杠或单引号进行字段分隔

我一直使用单引号进行字段分隔,例如:awk -F';' ...

对我来说相当新的是使用反斜杠的方式,例如:awk -F\; ...

两者之间是否存在技术差异,或者只是偏好问题?

答案1

这完全与你的 shell 有关,而不是与awk.

在类似 Bourne 的 shell 中,\'...'"..."都是引用运算符。

引用消除了字符在 shell 语法中可能具有的特殊含义。\引用单个字符(除了它删除的换行符),'...'并且"..."可以引用多个字符("..."不包含换行符)引用每个字符)。

;是 shell 语法中的特殊字符。它用于分隔命令。如果您想将其逐字传递给命令,则需要引用它。 \;';'会做。

";"也将执行 as;不是那些在双引号内仍然特殊的字符之一,但是您需要"\\"将一个文字反斜杠传递给命令,因为\是那些在双引号内仍然特殊的字符之一"..."(尽管只有在跟随时它才特殊)由其他特殊字符组成,"..."就像它本身一样")。

同样,这在很大程度上取决于外壳。rc例如,在shell 中,\"并不特殊,更不用说引用字符了,-F\;在那里不起作用,因为命令将被解析为以分隔的awk -F\ 和命令。...;

如何像普通字符一样使用特殊字符?更多细节。

让事情变得更加复杂的是,请注意论证-F本身经过一层或两层反斜杠处理通过 awk

awk首先处理它接收到的参数以扩展其中的 ANSI C 转义序列。如果使用awk -F '\t'orawk -F \\tawk -F "\\t"or awk -F "\t",则awk接收包含 的参数\t,并将其扩展为制表符。 awkFS变量将包含 TAB 字符,而不是\t

使用awk -F '\\',awk接收\\参数并设置FS\字符。严格来说,awk -F '\'will 是未指定的,因为转义序列尚未完成,但实际上,除了 busybox 之外awk,我知道的所有awk实现都将其视为与 相同awk -F '\\'

在 中awk,当FS包含单个字符时,该字符是字段分隔符。awk -F .按点字符分割记录。

但是,当FS包含多个字符时,它会被解释为正则表达式。awk -F ..不会溢出在两个点的序列上,而是溢出在任何两个字符的序列上,就像.匹配任何单个字符的正则表达式运算符一样。要分成两个点,您需要awk -F '[.][.]'awk -F '\\.\\.'

对于awk -F '\\\\',shell 将文字\\\\传递给awkawk将这两个中的每一个扩展为\\\因此FS变为\\,它被视为正则表达式。\在正则表达式语法中也比较特殊,用于去除字符的特殊含义作为正则表达式运算符这次。再次强调,这是在反斜杠字符上进行拆分,尽管这一次是作为正则表达式。

因此,在实践中,要拆分\,所有这些(在类似 Bourne 的 shell 中)都可以工作:

awk -F '\'      # FS becomes a single \ except in busybox where it's empty
awk -F "\\"     # instead so it's a one-character split on backslash
awk -F \\       # and a one-field-by-character split in busybox

awk -F '\\'     # FS becomes a single \ in every awk implementation
awk -F \\\\     # so one-character split on backslash
awk -F "\\\\"

awk -F '\\\'    # FS is \ on busybox and \\ in other implementations
awk -F \\\\\\   # so one-character split on backslash in busybox and
awk -F "\\\\\\" # \\ regex split in other implementations, to the same effect

awk -F '\\\\'     # FS is \\ in all implementations so
awk -F \\\\\\\\   # \\ regex split
awk -F "\\\\\\\"

我建议使用单引号,因为它们是最直接且最不令人惊讶的引号。所以在这里,要在反斜杠上进行可移植的分割:awk -F '\\'.

您还可以执行以下操作:

 awk -v FS='\\' ...

或者

 awk 'BEGIN{FS="\\"} ...'

或者

awk ... 'FS=\\'

或者:

FS='\' awk 'BEGIN{FS = ENVIRON["FS"]} ...'

(避免 执行额外的反斜杠扩展awk,因此只需要一个反斜杠)。

答案2

单引号内的所有字符均按字面意思处理(即一对单引号之间没有特殊字符)。如果没有单引号,如果要使用文字字符,则需要反斜杠转义具有特殊含义的字符。

这些是shell的引用规则,与awk无关。

相关内容