Awk 打印除前三列以外的所有列
太麻烦了:Awk 打印除前三列以外的所有列,awk,Awk,太麻烦了: awk '{print " "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13}' things 试试这个: awk '{ $1=""; $2=""; $3=""; print $0 }' echo 1 2 3 4 5 | awk'{for(i=3;i使用cut $ cut -f4-13 file 或者如果你坚持awk,最后一个字段是13美元 $ awk '{$1=$2=$3="";print}' file 否则 awk'
awk '{print " "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13}' things
试试这个:
awk '{ $1=""; $2=""; $3=""; print $0 }'
echo 1 2 3 4 5 | awk'{for(i=3;i使用cut
$ cut -f4-13 file
或者如果你坚持awk,最后一个字段是13美元
$ awk '{$1=$2=$3="";print}' file
否则
awk'{for(i=4;iawk'{for(i=1;i避免使用print语句的另一种方法:
$ awk '{$1=$2=$3=""}sub("^"FS"*","")' file
在awk中,当条件为真时,打印是默认操作。不添加额外前导或尾随的解决方案:
提供了一种在字段之间保留原始空白的解决方案:
$ echo '1 2 3 4 5 6 7' |
awk '{ sub(/([^ ]+ +){3}/,"") }1' |
tr ' ' '-'
4---5----6-7
还提供了两个很棒的解决方案:
(这些解决方案甚至保留原始字符串的尾随空格)
举例
$echo'1234567'
awk'{for(i=4;i目前几乎所有答案都添加了前导空格、尾随空格或其他一些分隔符问题。要使用awk
从第四个字段中选择分隔符为空白且输出分隔符为单个空格,请执行以下操作:
awk '{for(i=4;i<=NF;i++)printf "%s",$i (i==NF?ORS:OFS)}' file
awk'{for(i=4;i执行此操作的正确方法是使用RE间隔,因为它允许您简单地说明要跳过多少字段,并保留其余字段的字段间距
e、 g.鉴于我们在本问题中讨论的输入格式,在不影响剩余字段间距的情况下跳过前3个字段的步骤很简单:
$ echo '1 2 3 4 5 6' |
awk '{sub(/([^ ]+ +){3}/,"")}1'
4 5 6
如果您想容纳前导空格和非空格,但又使用默认的FS,那么它是:
$ echo ' 1 2 3 4 5 6' |
awk '{sub(/[[:space:]]*([^[:space:]]+[[:space:]]+){3}/,"")}1'
4 5 6
如果你有一个FS,你不能在字符集中否定它,你可以先将它转换成单个字符(RS是理想的,如果它是单个字符,因为RS不能出现在一个字段中,否则考虑子SEP),然后应用RE间隔子项,然后转换到OFS。例如,如果“.s”的链分隔字段:
$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,RS);sub("([^"RS"]+["RS"]+){3}","");gsub(RS,OFS)}1'
4 5 6
显然,如果OFS是单个字符,并且它不能出现在输入字段中,则可以将其减少为:
$ echo '1...2.3.4...5....6' |
awk -F'[.]+' '{gsub(FS,OFS); sub("([^"OFS"]+["OFS"]+){3}","")}1'
4 5 6
然后,您会遇到与所有重新分配字段的基于循环的解决方案相同的问题—FSs被转换为OFSs。如果这是一个问题,您需要研究GNU awks的patsplit()函数。这与前面的一些答案相去甚远,但确实解决了几个问题:
cols.sh
:
#!/bin/bash
awk -v s=$1 '{for(i=s; i<=NF;i++) printf "%-5s", $i; print "" }'
或:
这是1索引;如果您更喜欢零索引,请使用i=s+1
此外,如果您想使用起始索引和结束索引的参数,请将文件更改为:
#!/bin/bash
awk -v s=$1 -v e=$2 '{for(i=s; i<=e;i++) printf "%-5s", $i; print "" }'
%-5s
将结果对齐为5个字符宽的列;如果这还不够,请增加数字,或者如果您不关心对齐,则使用%s
(带空格)。基于AWK printf的解决方案避免了%问题,并且独特之处在于它不返回任何内容(无返回字符)如果要打印的列少于4列:
awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
awk'NF>3{for(i=4;i3{for(i=4;i3{for(i=4;i3{for(i=4;i我不敢相信没有人提供纯shell:
while read -r a b c d; do echo "$d"; done < file
读取时-r a b c d;执行回显“$d”;完成
输入
输出
4 5 6 7
不添加前导或尾随空格的Perl解决方案:
perl -lane 'splice @F,0,3; print join " ",@F' file
perl@F
自动拆分数组从索引0
开始,而awk字段从$1
开始
逗号分隔数据的Perl解决方案:
perl -F, -lane 'splice @F,0,3; print join ",",@F' file
Python解决方案:
$ echo '1 2 3 4 5 6 7' |
awk '{for(i=n;i<=NF;i++)$(i-(n-1))=$i;NF=NF-(n-1);print $0}' n=4 | tr ' ' '-'
4-5-6-7
python-c“导入sys;[sys.stdout.write(''.join(line.split()[3:])+'\n'),用于sys.stdin]中的行”
选项1到3有多个空格的问题(但很简单)。
这就是开发选项4和5的原因,它们处理多个空白没有问题。
当然,如果选项4或5与n=0
一起使用,这两个选项都将保留任何前导空格,因为n=0
意味着没有拆分
选择1
简单剪切解决方案(使用单个分隔符):
选择2
强制awk重新计算有时可以解决添加前导空格的问题(适用于某些版本的awk):
$ echo '1 2 3 4 5 6 7 8' | awk '{ $1=$2=$3="";$0=$0;} NF=NF'
4 5 6 7 8
选择3
打印使用printf
格式化的每个字段将提供更多控制:
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ for (i=n+1; i<=NF; i++){printf("%s%s",$i,i==NF?RS:OFS);} }'
4 5 6 7 8
它还可用于交换给定计数的字段列表n
:
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ a=gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1);
b=gensub("^(.*)("a")","\\1",1);
print "|"a"|","!"b"!";
}'
|4 5 6 7 8 | ! 1 2 3 !
当然,在这种情况下,OFS用于分隔行的两个部分,字段的尾随空白仍然打印
注1:[“FS”]*
用于在输入行中允许前导空格。Cut有一个--complete标志,使其变得简单(快速)删除列。生成的语法与您要执行的操作类似,使解决方案更易于阅读/理解。补码也适用于您要删除非连续列的情况
$ foo='1 2 3 %s 5 6 7'
$ echo "$foo" | cut --complement -d' ' -f1-3
%s 5 6 7
$
对我来说,最紧凑、最符合要求的解决方案是
$ a='1 2\t \t3 4 5 6 7 \t 8\t ';
$ echo -e "$a" | awk -v n=3 '{while (i<n) {i++; sub($1 FS"*", "")}; print $0}'
$a='12\t\t34567\t8\t';
$echo-e“$a”| awk-vn=3'{(i当我对第一个投票率很高但错误的答案感到恼火时,我发现足以在那里写一个答复,这里错误的答案被标记为这样,这是我的一点。我不喜欢提议的解决方案,因为我看不出有理由让答案如此复杂
我有一个日志,其中5美元后的IP地址可以是更多的文本或没有文本。我需要从IP地址到行尾的所有内容,如果5美元后有任何内容。在我的情况下,这实际上是一个awk程序,而不是一个awk单行程序,所以awk必须解决这个问题。当我尝试使用旧的美观和mo删除前4个字段时st投了赞成票,但回答完全错误:
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'
它给出了错误且无用的回答(我添加了[]以证明):
相反,如果列的宽度固定,直到需要切割点和awk,正确且非常简单的答案是:
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{printf "[%s]\n", substr($0,28)}'
它产生所需的输出:
[37.244.182.218 one two three]
我发现了另一种可能性,也许它也有用
awk'BEGIN{OFS=ORS=“\t”};{for(i=1;i使用cut:
cut -d <The character between characters> -f <number of first column>,<number of last column> <file name>
cut-d-f,
e、 g:如果您有文件1
包含:汽车.is.nice.equal.bmw
运行:cut-d.-f1,3 file1
将打印car.is.niceawk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$ x='1 2 3 %s 4 5 6'
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
%s 4 5 6
$ x='1 2 3'
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$ x='1 2 3 '
$ echo "$x" | awk 'NF > 3 { for(i=4; i<NF; i++) printf("%s ", $(i)); print $(i) }'
$
while read -r a b c d; do echo "$d"; done < file
awk '{$1=$2=$3="";$0=$0;$1=$1}1'
1 2 3 4 5 6 7
4 5 6 7
perl -lane 'splice @F,0,3; print join " ",@F' file
perl -F, -lane 'splice @F,0,3; print join ",",@F' file
$ echo '1 2 3 4 5 6 7 8' | cut -d' ' -f4-
4 5 6 7 8
$ echo '1 2 3 4 5 6 7 8' | awk '{ $1=$2=$3="";$0=$0;} NF=NF'
4 5 6 7 8
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ for (i=n+1; i<=NF; i++){printf("%s%s",$i,i==NF?RS:OFS);} }'
4 5 6 7 8
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ for(i=1;i<=n;i++) { sub("^["FS"]*[^"FS"]+["FS"]+","",$0);} } 1 '
4 5 6 7 8
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ print gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1); }'
4 5 6 7 8
$ echo ' 1 2 3 4 5 6 7 8 ' |
awk -v n=3 '{ a=gensub("["FS"]*([^"FS"]+["FS"]+){"n"}","",1);
b=gensub("^(.*)("a")","\\1",1);
print "|"a"|","!"b"!";
}'
|4 5 6 7 8 | ! 1 2 3 !
$ foo='1 2 3 %s 5 6 7'
$ echo "$foo" | cut --complement -d' ' -f1-3
%s 5 6 7
$
$ a='1 2\t \t3 4 5 6 7 \t 8\t ';
$ echo -e "$a" | awk -v n=3 '{while (i<n) {i++; sub($1 FS"*", "")}; print $0}'
$ awk -v n=3 '{i=0; while (i<n) {i++; sub($1 FS"*", "")}; print $0}' foo.txt
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{$1=$2=$3=$4=""; printf "[%s]\n", $0}'
[ 37.244.182.218 one two three]
echo " 7 27.10.16. Thu 11:57:18 37.244.182.218 one two three" | awk '{printf "[%s]\n", substr($0,28)}'
[37.244.182.218 one two three]
cut -d <The character between characters> -f <number of first column>,<number of last column> <file name>