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

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

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

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


当前回答

这应该是一个相当全面的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 "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

它使用awk打印除最后一个字段以外的所有字段

我对这里提供的awk解决方案都不满意,因为我想提取前几列,然后打印其余的,所以我转而使用perl。下面的代码提取了前两列,并按原样显示其余部分:

echo -e "a  b  c  d\te\t\tf g" | \
  perl -ne 'my @f = split /\s+/, $_, 3; printf "first: %s second: %s rest: %s", @f;'

与Chris Koknat的perl解决方案相比,优点是实际上只从输入字符串中分离出前n个元素;字符串的其余部分根本没有被分割,因此保持完整。我的示例混合使用空格和制表符来演示这一点。

要更改应该提取的列的数量,请将示例中的3替换为n+1。

打印从#2开始的列(输出在开始时没有尾随空格):

ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'
awk '{ for(i=3; i<=NF; ++i) printf $i""FS; print "" }'

Lauhub在这里提出了这个正确、简单、快速的解决方案

更新:

如果你想在保留空格和制表符的同时不使用任何函数调用,那么:

echo  "    1   2  33  4444 555555 \t6666666    " | 

{m,g}awk ++NF FS='^[ \t]*[^ \t]*[ \t]+|[ \t]+$' OFS= 

=

2  33  4444 555555     6666666

===================

你可以让它更直接:

 svn status | [m/g]awk   '/!/*sub("^[^ \t]*[ \t]+",_)'

 svn status |   [n]awk '(/!/)*sub("^[^ \t]*[ \t]+",_)'

自动处理管道中早期的grep,以及在删除$1后删除额外的FS,额外的好处是保留原始输入的其余部分,而不是用空格覆盖制表符(除非这是想要的效果)

如果你非常确定$1不包含需要regex转义的特殊字符,那么就更容易了:

mawk         '/!/*sub($!_"[ \t]+",_)'
gawk -c/P/e '/!/*sub($!_"""[ \t]+",_)' 

或者如果你更喜欢自定义FS+OFS来处理这一切:

mawk 'NF*=/!/' FS='^[^ \t]*[ \t]+' OFS='' # this version uses OFS