这行一直有效,直到我在第二个字段中留有空格。

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


是否可以用awk打印$ 2或更高的所有内容? ($ 3,$ 4 ..,直到没有更多的列了?)

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

评论

顺便说一句,grep | awk是反模式-您需要awk'/!/ {print $ 2}'

Unix“ cut”更容易... svn状态| grep'\!' |切-d''-f2-> removeProjs

在awk中可能会重复打印其余字段

@tripleee:很高兴您提到这个-到处都看到我很沮丧!

#1 楼

将打印除第一列之外的所有内容:

awk '{=""; print 
awk '{==""; print q4312078q}' somefile
}' somefile


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

评论


陷阱:留下一个关于:(

–raphinesse
13年1月8日,下午3:09

我喜欢务实的态度。尽管无需使用cat,只需将文件名放在awk命令之后。

– kon
2013年6月5日上午10:16

@raphinesse您可以使用awk'{$ 1 =“”来解决此问题。 print substr($ 0,2)}'输入文件名>输出文件名

–themiurgo
2013年9月12日15:07在

这不适用于非空白定界符,而是将它们替换为空格。

– Dejan
13年10月31日在19:28



对于非空白定界符,您可以指定输出字段分隔符(OFS),例如逗号:awk -F,-vOFS =,'{$ 1 =“ =”; print $ 0}',您将得到一个初始定界符($ 1仍作为空白字符串包含在内)。您可以使用sed删除它:awk -F,-vOFS =,'{$ 1 =“”;打印$ 0}'| sed's / ^,//'

– cherdt
16年7月7日在23:55

#2 楼

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

 svn status |  grep '\!' | cut -d\  -f2-


-d指定分隔符(空格),-f指定列列表(均从第二个开始)

评论


您也可以使用“ -b”指定位置(从第N个字符开始)。

– Dakatine
2013年9月10日13:56

需要注意的是,尽管它执行与awk版本相同的任务,但是存在cut的行缓冲问题,而awk没有该问题:stackoverflow.com/questions/14360640/…

– sdaau
13年11月26日在19:24

简洁漂亮,但有一个警告:awk会处理多个相邻的空格字符。作为单个分隔符,而剪切则不同样-尽管这在当前情况下不成问题-但cut只接受单个文字字符。作为分隔符,而awk允许使用正则表达式。

–mklement0
2014年1月21日14:55



基于此:stackoverflow.com/a/39217130/8852408,该解决方案可能效率不高。

–华金
18年7月19日在3:32

#3 楼

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

编辑:
因为“打印”追加一个换行符,您将要缓冲结果:

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"}'


评论


因此,我尝试了此操作,但认为我丢失了某些内容。.这是我所做的svn status | grep'\!' | gawk'{for(i = 1; i <= $ NF; i ++)print $ i“”;}'> removeProjs

–安迪
2010年6月2日在21:35

由于print会添加换行符,因此您需要缓冲结果。看到我的编辑。

–VeeArr
2010年6月2日,21:53

我更喜欢这个答案,因为它显示了如何遍历字段。

–爱德华·福克
2011年6月2日18:52

如果要打印使用空格,请更改输出记录分隔符:awk'{ORS =“”; for(i = 2; i
–克里斯蒂安·莱斯库(Christian Lescuyer)
2012年4月8日在8:10

总会有一些空间太多。这样效果更好:'{for(i = 11; i <= NF-1; i ++){printf“%s”,$ i}; print $ NF;}'没有前导或尾随空格。

– Marki
17年5月14日在18:09

#4 楼

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


我的回答基于VeeArr之一,但我注意到它以空白开头,然后才打印第二列(其余部分)。由于我只有1个信誉点,因此我无法对其进行评论,因此这里作为新答案:

以“ out”作为第二列,然后添加所有其他列(如果存在)。只要第二栏就可以了。

评论


太好了,您也删除了out变量前面的$,这也很重要。

– Alexis Wilke
2014年2月28日在1:29

#5 楼

大多数使用awk的解决方案都留有空格。这里的选项可以避免该问题。

选项1

简单的剪切解决方案(仅适用于单个定界符):

command | cut -d' ' -f3-


选项2

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

command | awk '{ =="";
$ 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
=
$ 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 , "" , 
$ 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 
) } 1 ' 3 4 5 6 7 8
;} NF=NF'


选项3

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

$ 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,q4312078q);
            print("|"d"|","!"e"!");
          }'
|3     4   5   6 7     8  | !    1    2  !


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

选项4(推荐)

带有sub的循环,以删除前面的字段和分隔符。
并且使用FS的值代替空间的值(可以更改)。
更便于携带,并且不会触发将FS更改为OFS:
注意:^[FS]*接受输入为前导空格。

q4312078q

选项5并使用GNU awk的功能gensub保留现有的空格,如下所示: :

q4312078q

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

注意:n用于在输入行中保留前导空格。

#6 楼

我亲自尝试了上面提到的所有答案,但是其中大多数答案有些复杂或不正确。从我的角度来看,最简单的方法是:

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



-F“”定义了awk使用的定界符。在我的情况下是空白,它也是awk的默认定界符。这意味着-F“”可以忽略。
其中NF定义了字段/列的总数。因此,循环将从第4个字段开始直到最后一个字段/列。
$ N检索第N个字段的值。因此,print $ i将基于循环计数打印当前字段/列。


评论


问题,将每个字段打印在不同的行上。

– mveroone
15年7月7日在13:39

没有什么可以阻止您将其附加在末尾:-)`| tr'\ n'''`

–koullislp
16-2-12在11:28



有点晚了,但是awk'{for(i = 5; i <= NF; i ++){printf“%s”,$ i}}'

–拆分器
18年8月8日在8:28

#7 楼

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


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

#8 楼

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

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

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


为避免键入所有内容,我猜最好的方法是可以做到的(请参见自动加载用户功能,网址为用awk启动吗?-Unix和Linux堆栈交换)是给~/.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);
}


评论


好像您要使用cut而不是awk

–roblogic
16年2月12日,下午2:31

#9 楼

这行得通吗?

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


前面还是留有空白。

#10 楼

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

ls -l | awk '{sub(/[^ ]+ /, ""); print q4312078q}'


评论


很好,尽管您应该在空格后加上+,因为字段可能被多个空格隔开(awk将多个相邻空格视为单个分隔符)。另外,awk会忽略前导空格,因此您应使用^ [] *开头正则表达式。使用空格作为分隔符,您甚至可以泛化解决方案。例如,以下代码从第三个字段返回所有内容:awk'{sub(/ ^ [] *([^] + +){2} /,“”); print $ 0}',但是使用任意字段分隔符会变得更加棘手。

–mklement0
2014年1月21日,16:04

#11 楼

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


此命令使用awk打印除最后一个字段以外的所有内容

#12 楼

这是我从所有建议中首选的:

从第6列到最后一列打印。

ls -lthr | awk '{out=; for(i=7;i<=NF;i++){out=out" "$i}; print out}'




ls -lthr | awk '{ORS=" "; for(i=6;i<=NF;i++) print $i;print "\n"}'


#13 楼

如果您需要用任意的分度号打印的特定列:

awk '{print  "  " }'



col#3 col#4


awk '{print  "anything" }'



col#3anythingcol#4


因此,如果一列中有空格,它将是两列,但您可以将其与任何定界符或没有定界符。

#14 楼

Perl解决方案:

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


使用以下命令行选项:


-n循环输入文件的每一行,不要自动打印每一行
-l在处理之前先删除换行符,然后再添加回去
-a自动拆分模式–将输入行拆分为@F数组。默认为在空格上分割
-e执行perl代码

splice @F,0,1从@F数组中彻底删除列0在每个元素之间使用空格


Python解决方案:

join " ",@F

#15 楼

如果您不想重新格式化行中没有切掉的部分,我可以想到的最佳解决方案是写在我的答案中:

如何在打印完之后的所有列使用awk特定数字吗?

它将对给定字段号N之前的内容进行斩波,并打印出所有行的其余部分,包括字段号N并保持原始间距(不重新格式化)。如果字段的字符串也出现在行中的其他位置,则不会发生问题。

定义一个函数:

fromField () { 
awk -v m="\x01" -v N="" '{$N=m$N; print substr(
$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 
,index(
svn status | grep '\!' | fromField 2 > removedProjs
,m)+1)}' }


并使用像这样:

awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr(q4312078q, index(q4312078q,m)+1)}'


输出可以维护所有内容,包括尾随空格

在您的特殊情况下:

q4312078q

如果文件/流的中间没有换行符(可以使用其他记录分隔符),则可以使用:

q4312078q

第一种情况仅在包含稀有十六进制字符1的文件/流中才会失败。

#16 楼

如果您使用的是Bash,并且可以使用尽可能多的'x'作为要丢弃的元素,那么它会起作用,并且如果不进行转义,它将忽略多个空格。

while read x b; do echo "$b"; done < filename


#17 楼

Perl:

@m=`ls -ltr dir | grep ^d | awk '{print $6,$7,$8,$9}'`;
foreach $i (@m)
{
        print "$i\n";

}


评论


这没有回答这个问题,该问题概括了从第N列到末尾打印的要求。

–roaima
2015年11月12日在10:49

#18 楼

awk函数返回begin的子字符串,其中包括从endb, e, p, i的字段:

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(
tail = fields(3);
, b + 1, e - b); }


要获取从字段3开始的所有内容: br />
要获取涵盖字段3至5的awk的部分,请执行以下操作:变量。

#19 楼

我想将提议的答案扩展到字段可能由多个空格分隔的情况–我想OP不使用cut的原因。方法可以在这里工作(例如从第5列到最后一个列打印示例):



sed -r 's/^\s*(\S+\s+){4}//' somefile

< br解释:



awk用于执行替换的标准方法

sed匹配行开头的任何连续空白

s///表示一列数据(非空白字符,后跟空白字符)

^\s*表示模式重复4次。



sed and cut


sed -r 's/^\s+//; s/\s+/\t/g' somefile | cut -f5-


,只需用单个制表符替换连续的空格即可;


tr和cut:
也可以使用\S+\s+选项来挤压连续的字符。

tr -s [:blank:] <somefile | cut -d' ' -f5-




#20 楼

Awk示例在这里看起来很复杂,这里是简单的Bash shell语法:

command | while read -a cols; do echo ${cols[@]:1}; done


其中1是从0开始计数的第n列。


示例

给出以下文件内容(in.txt):
c1
c1 c2
c1 c2 c3
c1 c2 c3 c4
c1 c2 c3 c4 c5


#21 楼

我对这里介绍的任何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。

#22 楼

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


这个答案还不错,但是自然间隔消失了。
然后将其与以下内容进行比较: >那么您会发现区别。

到目前为止,基于最佳投票答案的ls -la | awk '{==""; print}'都无法保留格式。

因此,我将使用以下内容,并且它也允许在开始时使用显式的选择性列:同样,例如,在下面的第1列和第3列为空,第2列为INFO,第4列为:

ls -la | cut -d\  -f4-


#23 楼

如果要格式化文本,请用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",,}'
   echo -en "$s3" | awk '{printf "|%-19s|\n", q4312078q}'
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 |
 


#24 楼

因为有340票错误的最upvoted anwser的,我只是失去了5分钟我的生活!在赞成之前有人有人尝试过这个答案吗?显然不是。完全没用。

我有一条日志,其中带有IP地址的$ 5之后可以是更多文本,也可以是没有文本。我需要从IP地址到行尾的所有内容,$ 5之后应该有东西。就我而言,这实际上是一个awk程序,而不是awk oneliner,因此awk必须解决该问题。当我尝试使用最受欢迎但完全错误的答案删除前4个字段时:

echo "  7 27.10.16. Thu 11:57:18 37.244.182.218" | awk '{====""; printf "[%s]\n", 
[    37.244.182.218 one two three]
}'


它吐出错误且无用的响应(我在[..]中添加了演示):

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


甚至还有一些暗示将substr与这个错误答案结合起来。像这样的并发症是一种进步。

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

q4312078q

产生所需的输出:

q4312078q