ChatGPT解决这个技术问题 Extra ChatGPT

如何使用“:”作为 AWK 字段分隔符?

给定以下命令,

echo "1: " | awk '/1/ -F ":" {print $1}'

为什么AWK输出:

1:

?


P
Peter Mortensen

“-F”是命令行参数,不是 AWK 语法。尝试:

 echo "1: " | awk -F  ":" '/1/ {print $1}'

这里无知的问题:/1/ 部分是告诉 awk 只处理包含数字 1 的行(或更准确地说是记录),对吗?
@rantsh awk 语法类似于 (pattern){action}。如果 pattern(主要是条件语句)为 true,则执行 action。如果 pattern 不可用,则隐含 true。这里的 pattern/1/,它声明 是正则表达式 1 在当前记录 $0 中匹配
作为旁注,如果分隔符是逗号,则需要将 -v OFS="," 参数添加到 awk,以将其保留在输出中
以及如何在 .awk 脚本中指出这一点?
@JoanSerrano 看看下面丹尼斯的答案,就是这样做的
D
Dennis Williamson

如果您想以编程方式执行此操作,可以使用 FS 变量:

echo "1: " | awk 'BEGIN { FS=":" } /1/ { print $1 }'

请注意,如果您在主循环而不是 BEGIN 循环中更改它,它会影响读入的 next 行,因为当前行已经被拆分。


f
fedorqui

您有多种方法可以将 : 设置为分隔符:

awk -F: '{print $1}'

awk -v FS=: '{print $1}'

awk '{print $1}' FS=:

awk 'BEGIN{FS=":"} {print $1}'

所有这些都是等效的,并且在给定示例输入“1:2:3”的情况下将返回 1

$ awk -F: '{print $1}' <<< "1:2:3"
1
$ awk -v FS=: '{print $1}' <<< "1:2:3"
1
$ awk '{print $1}' FS=: <<< "1:2:3"
1
$ awk 'BEGIN{FS=":"} {print $1}' <<< "1:2:3"
1

哪个是首选方式?我假设 BEGIN 语句的最后一个示例是最正确的(与整体 awk 语法一致)。
@randomware 他们都很好。如果我使用文件来存储整个内容,我倾向于使用 BEGIN,而 -F 在单行中会派上用场。
必须说,第三种情况与所有其他情况之间存在细微差别。示例:awk 'BEGIN{print split("foo:bar",a)}' FS=":" fileawk 'BEGIN{FS=":"; print split("foo:bar",a)}' file
谢谢!我从清晰的例子中学习得最好。
d
danben

-Fawk 本身的参数:

$echo "1: " | awk -F":" '/1/ {print $1}'
1

无需引用冒号。
P
Peter Mortensen

您还可以使用正则表达式作为字段分隔符。以下将通过使用正则表达式将数字“10”设置为分隔符来打印“bar”。

echo "foo 10 bar" | awk -F'[0-9][0-9]' '{print $2}'

P
Peter Mortensen

或者您可以使用:

echo "1: " | awk  '/1/{print $1-":"}' 

这是一个非常有趣的等式。


/1/ 是什么意思?
找到一个模式。在这种情况下“1”
为什么它是一个非常有趣的方程式?
我认为这个技巧只适用于“:”之前的值是数字。回声“ab1:”| awk '/1/{print $1-":"}' 失败,打印一个“0”
P
Peter Mortensen

没必要写这么多。只需将您想要的字段分隔符与 AWK 命令中的 -F 选项和您要打印的列号按照您提到的字段分隔符分开。

echo "1: " | awk -F: '{print $1}'
1

echo "1#2" | awk -F# '{print $1}'
1

P
Peter Mortensen

AWK 用作文本解释器,它对整个文档按行进行,对每一行按字段进行。因此 $1, $2...$n 是对每一行字段的引用($1 是第一个字段,$2 是第二个字段,依此类推...)。

您可以通过在命令行下使用“-F”开关或在带有“FS=...”的两个括号内定义字段分隔符。

现在考虑 the answer of Jürgen

echo "1: " | awk -F  ":" '/1/ {print $1}'

在字段上方,边界由“:”设置,因此我们有两个字段 $1 是“1”,而 $2 是空白区域。之后是正则表达式“/1/”,它指示过滤器仅在解释器偶然发现包含此类表达式的行(我的意思是 1)时才输出第一个字段。

“echo”命令的输出是包含“1”的一行,因此过滤器将起作用......

在处理以下示例时:

echo "1: " | awk '/1/ -F ":" {print $1}'

语法混乱,解释器选择忽略 F 部分“:”并切换到默认字段分隔符,即空白区域,因此输出“1:”作为第一个字段,不会有第二个字段!

Jürgen 的答案包含良好的语法......


它不是 awk 忽略它 - awk 将其读取为一个正则表达式的布尔结果 (1 / 0),然后是 numerically minus 一个名为 F 的变量,然后是带有单个冒号 (:) 的字符串连接,这意味着总模式产生真,因为它是一个非空字符串,因此 $1 默认分割空间被打印
R
RARE Kpop Manifesto
echo "1: " | "456:abc:515:xyz "

awk -F: NF=/1/

      1    |  456

更新:意识到我之前的回答有多冗长