这一行一直工作到第二个字段中出现空白。

svn status | grep '\!' | gawk '{print $2;}' > removedProjs

有没有办法让awk打印所有2美元或更大的东西?(3、4美元. .直到我们不再有专栏了?)

我想我应该补充一点,我正在使用Cygwin在Windows环境中执行此操作。


当前回答

您可以使用for循环来循环打印字段$2到$NF(表示行上字段数量的内置变量)。

编辑: 由于"print"附加了换行符,你需要缓冲结果:

awk '{out = ""; for (i = 2; i <= NF; i++) {out = out " " $i}; print out}'

或者,使用printf:

awk '{for (i = 2; i <= NF; i++) {printf "%s ", $i}; printf "\n"}'

其他回答

我个人尝试了上面提到的所有答案,但大多数都有点复杂或不正确。在我看来,最简单的方法是:

awk -F" " '{ for (i=4; i<=NF; i++) print $i }'

其中-F" "定义了awk使用的分隔符。在我的例子中是空格,它也是awk的默认分隔符。这意味着-F" "可以被忽略。 其中NF定义字段/列的总数。因此,循环将从第4个字段开始,一直到最后一个字段/列。 其中$N检索第N个字段的值。因此,print $i将根据循环计数打印当前字段/列。

这应该是一个相当全面的awk-field子字符串提取函数

根据输入范围返回$0的子字符串,包括 夹入超出范围的值, 处理可变长度字段SEPs 加速治疗::

完全没有输入,直接返回$0 输入值导致有保证的空字符串("") FROM-field == 1 FS = "",将$0按单个字符分割 (因此FROM <(_)>和TO <(__)>字段的行为像cut -c而不是cut -f)

原始$0恢复,w/o覆盖FS seps与OFS

|

 {m,g}awk '{
 2         print "\n|---BEFORE-------------------------\n"
 3         ($0) "\n|----------------------------\n\n  ["
 4         fld2(2, 5) "]\n  [" fld2(3) "]\n  [" fld2(4, 2)
 5         "]<----------------------------------------------should be
 6         empty\n  [" fld2(3, 11) "]<------------------------should be
 7         capped by NF\n  [" fld2() "]\n  [" fld2((OFS=FS="")*($0=$0)+11,
 8         23) "]<-------------------FS=\"\", split by chars
 9         \n\n|---AFTER-------------------------\n" ($0)
10         "\n|----------------------------"
11  }


12  function fld2(_,__,___,____,_____)
13  {
           if (+__==(_=-_<+_ ?+_:_<_) || (___=____="")==__ || !NF) {
              return $_
16         } else if (NF<_ || (__=NF<+__?NF:+__)<(_=+_?_:!_)) {
              return ___
18         } else if (___==FS || _==!___) {
19            return ___<FS \
                 ? substr("",$!_=$!_ substr("",__=$!(NF=__)))__
20               : substr($(_<_),_,__)
21         }
22         _____=$+(____=___="\37\36\35\32\31\30\27\26\25"\
                              "\24\23\21\20\17\16\6\5\4\3\2\1")
23         NF=__
24         if ($(!_)~("["(___)"]")) {
25            gsub("..","\\&&",___) + gsub(".",___,____)
27            ___=____
28         }
29         __=(_) substr("",_+=_^=_<_)

30         while(___!="") {
31            if ($(!_)!~(____=substr(___,--_,++_))) {
32               ___=____
33            break }
35            ___=substr(___,_+_^(!_))
36         }
37         return \
           substr("",($__=___ $__)==(__=substr($!_,
              _+index($!_,___))),_*($!_=_____))(__)
    }'

那些<TAB>是实际的\t \011,但为了显示清晰度重新标记

|---BEFORE------------------------- 
       1   2  33  4444 555555 <TAB>6666666    
|----------------------------

  [2 33 4444 555555]
  [33]
  []<---------------------------------------------- should be empty
  [33 4444 555555 6666666]<------------------------ should be capped by NF
  [       1   2  33  4444 555555 <TAB>6666666    ]
  [ 2  33  4444 555555 <TAB>66]<------------------- FS="", split by chars 

|---AFTER------------------------- 
       1   2  33  4444 555555 <TAB>6666666    
|----------------------------

如果你想要格式化文本,用echo链接你的命令并使用$0打印最后一个字段。

例子:

for i in {8..11}; do
   s1="$i"
   s2="str$i"
   s3="str with spaces $i"
   echo -n "$s1 $s2" | awk '{printf "|%3d|%6s",$1,$2}'
   echo -en "$s3" | awk '{printf "|%-19s|\n", $0}'
done

打印:

|  8|  str8|str with spaces 8  |
|  9|  str9|str with spaces 9  |
| 10| str10|str with spaces 10 |
| 11| str11|str with spaces 11 |

使用awk的大多数解决方案都留有空间。这里的选项避免了这个问题。

选项1

一个简单的切割解决方案(只适用于单个分隔符):

command | cut -d' ' -f3-

选项2

强制awk重新计算有时会通过删除第一个字段来删除添加的前导空格(OFS)(适用于某些版本的awk):

command | awk '{ $1=$2="";$0=$0;} NF=NF'

选项3

打印printf格式的每个字段将提供更多的控制:

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in"|awk -v n=2 '{ for(i=n+1;i<=NF;i++) printf("%s%s",$i,i==NF?RS:OFS);}'
3 4 5 6 7 8

但是,所有之前的答案都将字段之间的所有重复FS更改为OFS。让我们创建一些选项,不做这些。

选项4(推荐)

带有sub的循环删除前面的字段和分隔符。 并且使用FS的值而不是space(可以更改)。 更易于移植,并且不会触发FS到OFS的更改: 注意:^[FS]*是接受前导空格的输入。

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in" | awk '{ n=2; a="^["FS"]*[^"FS"]+["FS"]+";
  for(i=1;i<=n;i++) sub( a , "" , $0 ) } 1 '
3     4   5   6 7     8

选择5

很有可能构建一个不添加额外(前导或尾随)空白的解决方案,并使用GNU awk中的gensub函数保留现有的空白,如下所示:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          { print(gensub(a""b""c,"",1)); }'
3     4   5   6 7     8 

它也可以用来交换一组给定计数n的字段:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          {
            d=gensub(a""b""c,"",1);
            e=gensub("^(.*)"d,"\\1",1,$0);
            print("|"d"|","!"e"!");
          }'
|3     4   5   6 7     8  | !    1    2  !

当然,在这种情况下,OFS将用于分隔行的两个部分,并且仍然打印字段后面的空白。

注意:[FS]*用于在输入行中允许前导空格。

您可以使用for循环来循环打印字段$2到$NF(表示行上字段数量的内置变量)。

编辑: 由于"print"附加了换行符,你需要缓冲结果:

awk '{out = ""; for (i = 2; i <= NF; i++) {out = out " " $i}; print out}'

或者,使用printf:

awk '{for (i = 2; i <= NF; i++) {printf "%s ", $i}; printf "\n"}'