svn status | grep '\!' | gawk '{print ;}' > removedProjs
是否可以用awk打印$ 2或更高的所有内容? ($ 3,$ 4 ..,直到没有更多的列了?)
我想我应该补充一点,我正在Windows环境中使用Cygwin进行此操作。
#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
的子字符串,其中包括从end
到b, 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
评论
顺便说一句,grep | awk是反模式-您需要awk'/!/ {print $ 2}'Unix“ cut”更容易... svn状态| grep'\!' |切-d''-f2-> removeProjs
在awk中可能会重复打印其余字段
@tripleee:很高兴您提到这个-到处都看到我很沮丧!