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

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    
|----------------------------

其他回答

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

我的答案是基于VeeArr的答案,但我注意到它在打印第二列(以及其余部分)之前以空白开始。因为我只有1个声望点,所以我不能评论它,所以这是一个新的答案:

以“out”作为第二列开始,然后添加所有其他列(如果存在)。只要有第二列,这就很好。

ls -la | awk '{o=$1" "$3; for (i=5; i<=NF; i++) o=o" "$i; print o }'

这个答案还不错,但是自然的间隔消失了。 请将它与这个进行比较:

ls -la | cut -d\  -f4-

然后你就会看到区别了。

甚至ls -la | awk '{$1=$2="";打印},这是基于迄今为止投票选出的最佳答案,即不保留格式。

因此,我将使用以下,它还允许显式选择列在开始:

ls -la | cut -d\  -f1,4-

注意,每个空格也计算列,例如在下面,列1和列3是空的,2是INFO, 4是:

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f1,3

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f2,4
INFO 2014-10-11
$

zed_0xff投票最多的答案不适合我。

我有一个日志,其中$5与IP地址可以是更多的文本或没有文本。我需要从IP地址到行尾的所有内容,如果有任何在$5之后。在我的例子中,这实际上是在一个awk程序中,而不是awk一行程序,因此awk必须解决这个问题。当我试图删除前4个字段使用zed_0xff提出的解决方案:

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'

它吐出错误和无用的回应(我添加了[..]以示范):

[    37.244.182.218 one two three]

甚至有人建议将substr与这个错误的答案结合起来,但这只会使事情复杂化。它没有提供任何改进。

相反,如果列的宽度是固定的,直到需要切割点和awk,正确答案是:

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{printf "[%s]\n", substr($0,28)}'

它产生所需的输出:

[37.244.182.218 one two three]

您可以使用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"}'

在这里给出的所有其他答案以及在相关问题中给出的各种可能的FS值都以各种方式失败。有些在开头和/或结尾留下空白,有些将每个FS转换为OFS,有些依赖于仅当FS为默认值时才适用的语义,有些依赖于在括号表达式中否定FS,这将在给定多字符FS时失败,等等。

为了对任何FS都健壮地做到这一点,使用GNU awk的第4个参数split():

$ cat tst.awk
{
    split($0,flds,FS,seps)
    for ( i=n; i<=NF; i++ ) {
        printf "%s%s", flds[i], seps[i]
    }
    print ""
}

$ printf 'a b c d\n' | awk -v n=3 -f tst.awk c d $ printf ' a b c d\n' | awk -v n=3 -f tst.awk c d $ printf ' a b c d\n' | awk -v n=3 -F'[ ]' -f tst.awk b c d $ printf ' a b c d\n' | awk -v n=3 -F'[ ]+' -f tst.awk b c d $ printf 'a###b###c###d\n' | awk -v n=3 -F'###' -f tst.awk c###d $ printf '###a###b###c###d\n' | awk -v n=3 -F'###' -f tst.awk b###c###d Note that I'm using split() above because it's 3rg arg is a field separator, not just a regexp like the 2nd arg to match(). The difference is that field separators have additional semantics to regexps such as skipping leading and/or trailing blanks when the separator is a single blank char - if you wanted to use a while(match()) loop or any form of *sub() to emulate the above then you'd need to write code to implement those semantics whereas split() already implements them for you.