使用awk打印从第n个到最后一个的所有列

And*_*ndy 284 linux awk

这条线有效,直到我在第二个字段中有空格.

svn status | grep '\!' | gawk '{print $2;}' > removedProjs
Run Code Online (Sandbox Code Playgroud)

有没有办法让awk打印出2美元或更高的价格?($ 3,$ 4 ..直到我们没有列?)

我想我应该补充一点,我在Cygwin的Windows环境中这样做.

zed*_*xff 448

将打印所有但非常第一列:

awk '{$1=""; print $0}' somefile
Run Code Online (Sandbox Code Playgroud)

将打印除第一列以外的所有列:

awk '{$1=$2=""; print $0}' somefile
Run Code Online (Sandbox Code Playgroud)

  • 陷阱:留下一个悬空的领先空间:( (80认同)
  • @raphinesse你可以用'awk'解决这个问题{$ 1 =""; print substr($ 0,2)}'input_filename> output_filename` (42认同)
  • 这不适用于非空白分隔符,用空格替换它们. (6认同)
  • 我喜欢务实的做法.不需要使用cat,只需在awk命令后输入文件名即可. (5认同)
  • 正是我所需要的!现在,如果我想排除第 1-8 列,有没有办法在其中放置一个范围?而不是 `$1=$2=$3=$4=$5=$6=$7=$8=""` (2认同)
  • 对于非空白分隔符,您可以指定输出字段分隔符(OFS),例如逗号:`awk -F,-vOFS =,'{$ 1 =""; print $ 0}'`你最终将得到一个初始分隔符(仍然包含`$ 1`,就像一个空字符串).您可以使用`sed`删除它:`awk -F,-vOFS =,'{$ 1 =""; 打印$ 0}'| sed's/^,//'` (2认同)
  • AWK就像是一个过分直率的精灵,许诺了三个愿望 (2认同)

Jos*_*erg 93

有一个重复的问题,使用cut 更简单的答案:

 svn status |  grep '\!' | cut -d\  -f2-
Run Code Online (Sandbox Code Playgroud)

-d指定分隔符(空格),-f指定列的列表(全部以第2开头)

  • 很好,很简单,但有一个警告:`awk`处理多个相邻的空间字符.作为*single*分隔符,而`cut`则不是; 另外 - 虽然这在手头的情况下不是问题 - `cut`只接受单个字面字符.作为分隔符,而`awk`允许正则表达式. (20认同)
  • @mklement0我发现[这个答案](/sf/answers/1503369871/)应该有所帮助。即`echo "fo o bar r" | tr -s ' ' | 切-d''-f3-` (2认同)

Vee*_*Arr 80

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

编辑:由于"print"附加换行符,因此您需要缓冲结果:

awk '{out=""; for(i=2;i<=NF;i++){out=out" "$i}; print out}'
Run Code Online (Sandbox Code Playgroud)

或者,使用printf:

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

  • 如果要打印使用空格,请更改输出记录分隔符:awk'{ORS =""; for(i = 2; i <NF; i ++)print $ i}'somefile (3认同)
  • 总会有一些空间太多。效果更好:`'{for(i = 11; i &lt;= NF-1; i ++){printf“%s”,$ i}; print $ NF;}'`没有前导或尾随空格。 (3认同)
  • 我更喜欢这个答案,因为它展示了如何循环字段。 (2认同)

Wim*_*Wim 23

awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'
Run Code Online (Sandbox Code Playgroud)

我的回答是基于VeeArr的一个,但是我注意到它在打印第二列(以及其余列)之前以空​​格开头.由于我只有1个声望点,我无法评论它,所以这里作为一个新的答案:

以"out"作为第二列开始,然后添加所有其他列(如果它们存在).只要有第二列,这就顺利进行.

  • 很好,你也删除了out变量前面的$,这也很重要. (2认同)

小智 14

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

选项1

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

command | cut -d' ' -f3-
Run Code Online (Sandbox Code Playgroud)

选项2

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

command | awk '{ $1=$2="";$0=$0;} NF=NF'
Run Code Online (Sandbox Code Playgroud)

选项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
Run Code Online (Sandbox Code Playgroud)

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

选项4(推荐)

带有sub的循环,用于删除前面的字段和分隔符.
并使用FS的值而不是空间(可以更改).
更便于携带,并且不会触发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
Run Code Online (Sandbox Code Playgroud)

选项5

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

$ 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 
Run Code Online (Sandbox Code Playgroud)

它还可用于交换给定计数的一组字段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  !
Run Code Online (Sandbox Code Playgroud)

当然,在这种情况下,OFS用于分离线的两个部分,并且仍然打印字段的尾随空白区域.

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


kou*_*slp 12

我亲自尝试了上面提到的所有答案,但大多数都有点复杂或者说不对.从我的角度来看,最简单的方法是:

awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
Run Code Online (Sandbox Code Playgroud)
  1. 其中-F""定义awk使用的分隔符.在我的例子中是空格,它也是awk的默认分隔符.这意味着可以忽略-F"".

  2. NF定义字段/列的总数.因此,循环将从第4个字段开始直到最后一个字段/列.

  3. $ N检索第N个字段的值.因此print $ i将根据循环计数打印当前字段/列.

  • 有点晚了,但是awk'{for(i = 5; i &lt;= NF; i ++){printf“%s”,$ i}}' (3认同)
  • 问题,在不同的行上打印每个字段. (2认同)

sda*_*aau 6

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

首先,创建一个名为的新Awk库脚本pfcut,例如

sudo nano /usr/share/awk/pfcut
Run Code Online (Sandbox Code Playgroud)

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

$ 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
Run Code Online (Sandbox Code Playgroud)

为了避免输入所有这些,我想最好的可以做(请参阅否则在启动时使用awk自动加载用户功能? - Unix和Linux Stack Exchange)添加别名~/.bashrc; 例如:

$ echo "alias awk-pfcut='awk -f pfcut --source'" >> ~/.bashrc
$ source ~/.bashrc     # refresh bash aliases
Run Code Online (Sandbox Code Playgroud)

...然后你可以打电话:

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

这是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);
}
Run Code Online (Sandbox Code Playgroud)


wha*_*ley 5

这会有用吗?

awk '{print substr($0,length($1)+1);}' < file
Run Code Online (Sandbox Code Playgroud)

它虽然留下了一些空白.


小智 5

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

ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'
Run Code Online (Sandbox Code Playgroud)


aje*_*rex 5

awk '{ for(i=3; i<=NF; ++i) printf $i""FS; print "" }'
Run Code Online (Sandbox Code Playgroud)

lauhub 在这里提出了这个正确,简单和快速的解决方案


归档时间:

查看次数:

431420 次

最近记录:

7 年,2 月 前