【问题标题】:Awk command to print from 3rd column to till nth columnawk 命令从第 3 列打印到第 n 列
【发布时间】:2016-09-21 09:42:29
【问题描述】:

如果文件中有“n”列,如何在 unix 中使用 awk 命令从第三列打印到最后一列。我正在使用 cut 命令,但我需要 awk 命令。我正在尝试使用awk -F " " '{ for{i=3;i<=NF;i++) print $i}',我得到了输出,但它的格式不正确。谁能建议我正确的命令。

【问题讨论】:

  • 你能给出示例输入/输出...列的空间是否分隔?
  • cut 有什么问题?

标签: unix awk


【解决方案1】:

结合 Ed Morton 的答案:

我们得到这样的结果:

awk '{sub(/^(\S+\s*){2}/,""); sub(/(\s*\S+){2}$/,"")}1'
#     ^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^
#     remove 2 first cols      remove 2 last cols

您可以根据列的具体需求进行调整。

查看给出此输入的示例:

$ paste -d ' ' <(seq 5) <(seq 2 6) <(seq 3 7) <(seq 4 8) <(seq 5 9) 
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9

让我们打印第三列:

$ awk '{sub(/^(\S+\s*){2}/,""); sub(/(\s*\S+){2}$/,"")}1' <(paste -d ' ' <(seq 5) <(seq 2 6) <(seq 3 7) <(seq 4 8) <(seq 5 9))
3
4
5
6
7

【讨论】:

  • @karakfa 这不是太通用:)
【解决方案2】:

您的尝试很接近,但似乎它将在新行上打印每一列。 为了纠正这个问题,我们创建了一个名为“line”的变量并将其初始化为一个空字符串。我们第一次进入循环时,我们只需将列添加到“行”。从那时起,我们将使用字段分隔符和下一列附加到“行”。最后,我们打印'line'。这将发生在文件中的每一行。

awk '{line="";for(i=3;i<=NF;i++) if(i==3) line=$i; else line=line FS $i; print line}'

在本例中,我假设使用 awk 的默认字段分隔符。此外,任何少于三行的行都将打印空行。

【讨论】:

    【解决方案3】:

    假设您的字段是空格分隔的,然后使用 GNU awk for gensub():

    $ cat file
    a b c d e f
    g h i j k l
    
    $ awk '{print gensub(/(\S\s){2}/,"",1)}' file
    c d e f
    i j k l
    

    如果使用 GNU awk 再次使用 gensub() 从字段 3 到字段 5 进行空白分隔,则通常从字段 3 打印到字段 5:

    $ awk '{print gensub(/(\S\s){2}((\S\s){2}\S).*/,"\\2",1)}' file
    c d e
    i j k
    

    或匹配的第三个参数():

    $ awk 'match($0,/(\S\s){2}((\S\s){2}\S)/,a){print a[2]}' file
    c d e
    i j k
    

    或者一般来说,如果它们被任何单个字符分隔:

    $ awk '{print gensub("([^"FS"]"FS"){2}(([^"FS"]"FS"){2}[^"FS"]).*","\\2",1)}' file
    c d e
    i j k
    
    $ awk 'match($0,"([^"FS"]"FS"){2}(([^"FS"]"FS"){2}[^"FS"])",a){print a[2]}' file
    c d e
    i j k
    

    如果字段由字符串而不是单个字符分隔,但 RS 是单个字符,那么您应该暂时将 FS 更改为 RS(根据定义,您知道它不能出现在记录中),这样您就可以在括号表达式中否定它:

    $ cat file
    aSOMESTRINGbSOMESTRINGcSOMESTRINGdSOMESTRINGeSOMESTRINGf
    gSOMESTRINGhSOMESTRINGiSOMESTRINGjSOMESTRINGkSOMESTRINGl
    
    $ awk -F'SOMESTRING' '{gsub(FS,RS)} match($0,"([^"RS"]"RS"){2}(([^"RS"]"RS"){2}[^"RS"])",a){gsub(RS,FS,a[2]); print a[2]}' file
    cSOMESTRINGdSOMESTRINGe
    iSOMESTRINGjSOMESTRINGk
    

    如果 FS 和 RS 都是多字符,那么有多种选择,但最简单的方法是使用 NUL 字符或您知道不能出现在输入文件中的其他字符,而不是 RS 作为临时替换 FS:

    $ awk -F'SOMESTRING' '{gsub(FS,"\0")} match($0,/([^\0]\0){2}(([^\0]\0){2}[^\0])/,a){gsub("\0",FS,a[2]); print a[2]}' file
    cSOMESTRINGdSOMESTRINGe
    iSOMESTRINGjSOMESTRINGk
    

    如果需要,显然可以在上面最后的 gsub() 中将 FS 更改为 OFS。

    如果 FS 是一个正则表达式而不是一个字符串,并且您希望将其保留在输出中,那么您需要查看 GNU awk 以获取 split() 的第 4 个参数。

    【讨论】:

    • 太棒了!! ++++++
    【解决方案4】:

    如果你不介意规范化空间,最直接的方法是

    $ awk '{$1=$2=""}1' | sed -r 's/^ +//'
    

    在行动

    $ seq 11 40 | pr -6ts' ' | awk '{$1=$2=""}1' | sed -r 's/^ +//'
    
    21 26 31 36
    22 27 32 37
    23 28 33 38
    24 29 34 39
    25 30 35 40
    

    输入

    $ seq 11 40 | pr -6ts' '
    
    11 16 21 26 31 36
    12 17 22 27 32 37
    13 18 23 28 33 38
    14 19 24 29 34 39
    15 20 25 30 35 40
    

    【讨论】:

      【解决方案5】:

      从第三列打印到最后 cat 文件名|awk '{for(i=1;i

      【讨论】:

        猜你喜欢
        • 2021-11-25
        • 2023-02-04
        • 1970-01-01
        • 2011-02-27
        • 2017-04-23
        • 1970-01-01
        • 2015-11-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多