我有一个示例数据集:
1
2
3
4
5
6
由以下awk命令成功解析为所需的输出
awk 'ORS=NR%3?FS:RS'
1 2 3
4 5 6
你能否解释这个命令的作用?我无法把各个部分组合在一起.
据我所知:
> ORS =输出记录分隔符 – 这就是我们希望RS用于最终输出,即3列的行
> NR%3 =我们希望将数据分组为3个元素的行
>?FS:RS – 不确定这是如何适应命令的.
谢谢.
解决方法:
%是模运算符(见https://en.wikipedia.org/wiki/Modulo_operation)和NR%3?FS:RS是三元表达式(见https://en.wikipedia.org/wiki/%3F:).这些都是许多编程语言中的常见结构,它们并不特定于awk.有关ORS,NR,FS和RS的含义,请参阅awk手册页.
运行此命令以查看正在执行的命令之前和之后代码中的变量值:
$cat tst.awk
BEGIN {
printf "%s=\"%s\"\n", "RS", RS
printf "%s=\"%s\"\n", "FS", FS
}
{
printf "---\n"
printf "%s=\"%s\"\n", "$0", $0
printf "%s=\"%s\"\n", "NR", NR
printf "%s=\"%s\"\n", "NR%3", NR%3
printf "before) %s=\"%s\"\n", "ORS", ORS
ORS = (NR%3 ? FS : RS)
printf "after) %s=\"%s\"\n", "ORS", ORS
}
.
$awk -f tst.awk file
RS="
"
FS=" "
---
$0="1"
NR="1"
NR%3="1"
before) ORS="
"
after) ORS=" "
---
$0="2"
NR="2"
NR%3="2"
before) ORS=" "
after) ORS=" "
---
$0="3"
NR="3"
NR%3="0"
before) ORS=" "
after) ORS="
"
---
$0="4"
NR="4"
NR%3="1"
before) ORS="
"
after) ORS=" "
---
$0="5"
NR="5"
NR%3="2"
before) ORS=" "
after) ORS=" "
---
$0="6"
NR="6"
NR%3="0"
before) ORS=" "
after) ORS="
"
请注意输出记录分隔符(ORS)的输入行号(NR)变为换行符(如RS)与空白字符(如FS).
编写相同代码的更详细的方法是:
$cat tst.awk
{
if (NR%3 == 0) {
ORS = "\n"
}
else {
ORS = " "
}
}
$awk -f tst.awk file
1 2 3
4 5 6
以及在你的问题中尝试编写简洁,惯用代码的正确(更强大和更清晰)的方法是:
awk '{ORS=(NR%3?FS:RS)}1'
在某些情况下,某些问题需要三元组周围的问题,并始终提高可读性,以便始终使用它们.原始代码依赖于赋予ORS的结果,产生非空/非零值,以使其成为真实条件,因此调用awks默认操作来打印当前记录.只有在您需要时才使用该上下文中的操作结果,否则当您的数据不完全符合预期时,它会在某一天咬你.我没有将赋值保留在条件块中,而是将其移动到一个动作块中,然后在之后添加一个常量的真实条件,1以确保每个记录都被打印,而不管该赋值是什么.
标签:linux,awk
来源: https://codeday.me/bug/20190827/1744624.html