关于使用ORS,NR,FS,RS的awk命令的说明

时间:2019-05-06 01:56:32

标签: linux awk

我有一个样本数据集:

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-不确定它是否适合命令。

谢谢。

3 个答案:

答案 0 :(得分:5)

Public Sub SetRangeNames(startRow As Integer, endRow As Integer) Dim currentRow As Long 'Long not Integer (always safer) For currentRow = startRow To endRow With ThisWorkbook.Sheets("SYSProjectData") 'worksheets Parent is the containing workbook .Parent.Names.Add Name:=.Cells(currentRow, "D"), _ RefersTo:=.Cells(currentRow, "C") End With Next currentRow End Sub 是模运算符(请参见https://en.wikipedia.org/wiki/Modulo_operation),而%是三元表达式(请参见https://en.wikipedia.org/wiki/%3F:)。这些都是许多编程语言中的常见构造,它们并非特定于awk。有关ORS,NR,FS和RS的含义,请参见awk手册页。

运行此命令,以在执行命令之前和之后查看代码中变量的值:

NR%3?FS:RS

$ 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=" " )在哪个输入行号(NR)变为换行符(如ORS)与空白字符(如RS)之间

编写相同代码的更详细的方法是:

FS

并且仅供参考,编写在您的问题中尝试过的简洁,惯用代码的正确方法(更强大,更清晰)是:

$ cat tst.awk
{
    if (NR%3 == 0) {
        ORS = "\n"
    }
    else {
        ORS = " "
    }

    print
}

$ awk -f tst.awk file
1 2 3
4 5 6

在某些情况下,在某些情况下需要三进制周围的括号,并且始终会提高可读性,因此请始终使用它们。原始代码依赖于分配给ORS的结果,该结果产生一个非空/非零值,以便使其成为真实条件,因此调用打印当前记录的awks默认动作。仅在需要时才在该上下文中使用操作的结果,否则有一天您的数据可能与您的预期不符时会咬住您。我没有将分配留在条件块中,而是将其移到动作块中,然后在其后添加了一个恒定的true条件,awk '{ORS=(NR%3?FS:RS)}1' 以确保打印每条记录,无论分配结果如何。

答案 1 :(得分:0)

对于每3条记录(NR-记录数),三元运算符的输出为0

这意味着满足0的第二个条件。

cond ? non-zero : zero

因此,RS被满意并且记录被分隔了-在这里用换行符,否则它是FS字段分隔的

答案 2 :(得分:0)

不是awk的解释,因为您已经有了多个答案,但是可以替代同一任务

$ seq 6 | xargs -n3
1 2 3
4 5 6

$ seq 6 | paste - - -
1       2       3
4       5       6

带有paste的默认定界符是制表符,您可以使用-d' '更改为空格

$ seq 6 | pr -3ats' '
1 2 3
4 5 6