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

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

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

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


当前回答

这样能行吗?

awk '{print substr($0,length($1)+1);}' < file

它在前面留下了一些空白。

其他回答

这让我非常恼火,我坐下来写了一个类似cut的字段规范解析器,用GNU Awk 3.1.7测试。

首先,创建一个新的Awk库脚本pfcut。

sudo nano /usr/share/awk/pfcut

然后,粘贴下面的脚本,并保存。之后,是这样的用法:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-4"); }'
t1 t2 t3 t4

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("2-"); }'
t2 t3 t4 t5 t6 t7

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

为了避免键入所有这些,我想最好的方法是(参见其他方法)在启动时自动加载用户函数?- Unix & Linux Stack Exchange)为~/.bashrc添加别名;例如:

$ echo "alias awk-pfcut='awk -f pfcut --source'" >> ~/.bashrc
$ source ~/.bashrc     # refresh bash aliases

... 然后你可以调用:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk-pfcut '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

以下是pfcut脚本的源代码:

# pfcut - print fields like cut
#
# sdaau, GNU GPL
# Nov, 2013

function spfcut(formatstring)
{
  # parse format string
  numsplitscomma = split(formatstring, fsa, ",");
  numspecparts = 0;
  split("", parts); # clear/initialize array (for e.g. `tail` piping into `awk`)
  for(i=1;i<=numsplitscomma;i++) {
    commapart=fsa[i];
    numsplitsminus = split(fsa[i], cpa, "-");
    # assume here a range is always just two parts: "a-b"
    # also assume user has already sorted the ranges
    #print numsplitsminus, cpa[1], cpa[2]; # debug
    if(numsplitsminus==2) {
     if ((cpa[1]) == "") cpa[1] = 1;
     if ((cpa[2]) == "") cpa[2] = NF;
     for(j=cpa[1];j<=cpa[2];j++) {
       parts[numspecparts++] = j;
     }
    } else parts[numspecparts++] = commapart;
  }
  n=asort(parts); outs="";
  for(i=1;i<=n;i++) {
    outs = outs sprintf("%s%s", $parts[i], (i==n)?"":OFS); 
    #print(i, parts[i]); # debug
  }
  return outs;
}

function pfcut(formatstring) {
  print spfcut(formatstring);
}

这个awk函数返回$0的子字符串,包含从开始到结束的字段:

function fields(begin, end,    b, e, p, i) {
    b = 0; e = 0; p = 0;
    for (i = 1; i <= NF; ++i) {
        if (begin == i) { b = p; }
        p += length($i);
        e = p;
        if (end == i) { break; }
        p += length(FS);
    }
    return substr($0, b + 1, e - b);
}

获取从字段3开始的所有内容:

tail = fields(3);

获取包含字段3到5的$0 section:

middle = fields(3, 5);

函数参数表中的B e p I是一种awk声明局部变量的方式。

Perl的解决方案:

perl -lane 'splice @F,0,1; print join " ",@F' file

使用这些命令行选项:

-n循环输入文件的每一行,不自动打印每一行 -l在处理之前删除换行符,并在处理之后将它们添加回去 -a autosplit mode -将输入行分割到@F数组中。默认为空格分割 -e执行perl代码

splice @F,0,1从@F数组中清除第0列

join " ",@F连接@F数组的元素,在每个元素之间使用一个空格


Python的解决方案:

[sys.stdout.]写(' ' . join (line.split () [1:]) + ' \ n ')系统的线。Stdin]" <文件

echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

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

使用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]*用于在输入行中允许前导空格。