【发布时间】:2011-07-02 04:49:39
【问题描述】:
在 shell 上,当我需要特定列时,我通过管道连接到 awk。
这将打印第 9 列,例如:
... | awk '{print $9}'
我如何告诉 awk 打印所有列包括第 9 列和之后的所有列,而不仅仅是第 9 列?
【问题讨论】:
在 shell 上,当我需要特定列时,我通过管道连接到 awk。
这将打印第 9 列,例如:
... | awk '{print $9}'
我如何告诉 awk 打印所有列包括第 9 列和之后的所有列,而不仅仅是第 9 列?
【问题讨论】:
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'
【讨论】:
awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'
cut 或perl。仅当您真的坚持要在 awk 中使用它时才使用它。
当您想要执行一系列字段时,awk 并没有直接的方法来执行此操作。我会推荐cut:
cut -d' ' -f 9- ./infile
由于默认为制表符,添加了空格字段分隔符。感谢 Glenn 指出这一点
【讨论】:
find . | xargs ls -l | cut -d' ' -f 9-。由于某种原因,双空格也被计算在内。示例:lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_b 将导致 ./file_a 00:06 ./file_b
awk '{print substr($0, index($0,$9))}'
编辑: 请注意,如果第九个之前的任何字段包含与第九个相同的值,这将不起作用。
【讨论】:
sed -re 's,\s+, ,g' | cut -d ' ' -f 9-
不处理可变宽度的空格,而是将所有空格替换为单个空格。然后对感兴趣的字段使用简单的cut。
它不使用 awk,因此没有密切关系,但考虑到其他答案/cmets,它似乎是合适的。
【讨论】:
ps faux | 使用的理想选择。永远不要害怕承认工具 XYZ 不是最合适的。
ps faux | perl -pe 's/^(\H*\h*){8}//'。看我的回答。
通常 perl 替换 awk/sed/grep 等。 al.,并且更更便携(以及只是一个更好的小刀)。
perl -lane 'print "@F[8..$#F]"'
Timtowtdi 当然适用。
【讨论】:
-l,或者添加\n。
awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'
这会删除给定字段 nr.、N 之前的内容,并打印该行的所有其余部分,包括字段 nr.N 并保持原始间距(它不会重新格式化)。字段的字符串是否也出现在该行的其他位置无关紧要,这是 Ascherer 的答案的问题。
定义一个函数:
fromField () {
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}
并像这样使用它:
$ echo " bat bi iru lau bost " | fromField 3
iru lau bost
$ echo " bat bi iru lau bost " | fromField 2
bi iru lau bost
输出维护所有内容,包括尾随空格 对于 N=0,它按原样返回整行,对于 n>NF,它返回空字符串
【讨论】:
这是ls -l 输出的示例:
-rwxr-----@ 1 ricky.john 1493847943 5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john 1493847943 27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john 1493847943 21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john 1493847943 10627144 Apr 16 14:09 03-Where to Get Help.mp4
我打印任何帖子$9 的解决方案是awk '{print substr($0, 61, 50)}'
【讨论】:
使用 cut 而不是 awk 并通过使用 -c 字符剪切命令来解决确定从哪一列开始的问题。
我在这里说,除了输出的前 49 个字符之外,给我所有字符。
ls -l /some/path/*/* | cut -c 50-
ls 命令末尾的/*/*/ 也告诉我子目录中的内容。
您还可以提取某些范围的字符 ala(从剪切的手册页中)。例如,显示当前登录用户的姓名和登录时间:
who | cut -c 1-16,26-38
【讨论】:
要显示前 3 个字段并打印您可以使用的剩余字段:
awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename
其中 $1 $2 $3 是前 3 个字段。
【讨论】:
function print_fields(field_num1, field_num2){
input_line = $0
j = 1;
for (i=field_num1; i <= field_num2; i++){
$(j++) = $(i);
}
NF = field_num2 - field_num1 + 1;
print $0
$0 = input_line
}
【讨论】:
通常希望传递剩余的列未修改。也就是说,不会折叠连续的空白。
想象一下处理ls -l 或ps faux 的输出的情况(不推荐,仅给出最后一列可能包含空格序列的示例))。我们希望保留剩余列中的任何连续空白,以便名为my file.txt 的文件不会变为my file.txt。
使用awk 为行的其余部分保留空白非常困难。接受的基于 awk 的答案不会,即使有建议的改进。
sed 或 perl 更适合这项任务。
sed
echo '1 2 3 4 5 6 7 8 9 10' | sed -E 's/^([^ \t]*[ \t]*){8}//'
结果:
9 10
-E 选项启用现代 ERE 正则表达式语法。这样就省去了反斜杠转义括号和大括号的麻烦。
{8} 是一个量词,表示与前一项精确匹配 8 次。
sed s 命令用空字符串替换出现的 8 次空格分隔的单词。该行的其余部分保持不变。
perl
Perl regex 支持水平空格的\h 转义。
echo '1 2 3 4 5 6 7 8 9 10' | perl -pe 's/^(\H*\h*){8}//'
结果:
9 10
【讨论】:
ruby -lane 'print $F[3..-1].join(" ")' file
【讨论】: