我有一个文件,每行中有很多行,每行有很多列(字段),用空格“”隔开,每行中的列数不同。我想删除前两列怎么办?
Answers:
您可以使用cut
:
cut -d " " -f 3- input_filename > output_filename
说明:
cut
:调用cut命令-d " "
:使用单个空格作为分隔符(cut
默认情况下使用TAB)-f
:指定要保留的字段3-
:以字段3开头的所有字段input_filename
:使用此文件作为输入> output_filename
:将输出写入此文件。或者,您可以使用awk
:
awk '{$1=""; $2=""; sub(" ", " "); print}' input_filename > output_filename
说明:
awk
:调用awk命令$1=""; $2="";
:将字段1和2设置为空字符串sub(...);
:清理输出字段,因为字段1和2仍将由“”分隔print
:打印修改后的行input_filename > output_filename
:与上述相同。cut
默认使用制表符作为分隔符。查看更新的答案-刚刚经过测试,即可正常工作。在其他条件相同的情况下,我建议使用cut
over awk
。
awk '{sub(/([^ ]+ ){2}/, "")}1'
。我同意,如果您有单字符字段分隔符,无论如何,cut是更好的选择。
awk '{$1=""; $2=""; sub(/^ +/, ""); print}'
代替,或者用更短的空格awk '{$1=$2=""; sub(/^ +/, "")}1'
这是使用Awk相对容易理解的一种方法:
awk '{print substr($0, index($0, $3))}'
这是一个简单的awk命令,没有任何模式,因此将对{}
每个输入行运行内部操作。
操作是仅从第三个字段的位置开始打印子字符串。
$0
:整个输入行$3
:第三场index(in, find)
:返回find
字符串中的位置in
substr(string, start)
:返回从索引开始的子字符串 start
如果要使用其他定界符(例如逗号),则可以使用-F选项进行指定:
awk -F"," '{print substr($0, index($0, $3))}'
您还可以通过在中的操作之前指定模式来对输入行的子集进行操作{}
。只有与模式匹配的行才会执行操作。
awk 'pattern{print substr($0, index($0, $3))}'
模式可以是这样的:
/abcdef/
:使用正则表达式,默认情况下对$ 0进行运算。$1 ~ /abcdef/
:在特定字段上操作。$1 == blabla
:使用字符串比较NR > 1
:使用记录/行号NF > 0
:使用字段/列号感谢您发布问题。我还想添加对我有帮助的脚本。
awk '{ $1=""; print $0 }' file
OFS=FS
以保留定界符:unix.stackexchange.com/a/252748/112834
您可以使用sed
:
sed 's/^[^ ][^ ]* [^ ][^ ]* //'
这将查找以一个或多个非空白,一个空格,另一组一个或多个非空白和另一个空格开头的行,并删除匹配的材料,也就是前两个字段。它[^ ][^ ]*
比等效但更明确的[^ ]\{1,\}
符号略短,并且第二个符号可能会与GNU发生问题sed
(尽管如果您将其--posix
用作选项,即使GNUsed
也无法解决)。OTOH,如果要重复的字符类别更为复杂,则为简明起见,用数字表示法是可以取胜的。很容易将其扩展为将“空白或制表符”作为分隔符,或“多个空白”或“多个空白或制表符”。还可以对其进行修改,以处理第一个字段之前的可选前导空白(或制表符),等等。
对于awk
和cut
,请参阅Sampson-Chen的答案。还有其他编写awk
脚本的方法,但是从本质上说,它们并不比给出的答案更好。请注意,如果您不希望将制表符视为分隔符,则可能需要显式设置字段分隔符(-F" "
),awk
否则字段之间可能会有多个空白。POSIX标准cut
不支持字段之间的多个分隔符。GNUcut
具有有用但非标准的-i
选项,以允许在字段之间使用多个分隔符。
您也可以在纯shell中执行此操作:
while read junk1 junk2 residue
do echo "$residue"
done < in-file > out-file
residue
可以包含反斜杠,则上述读取内容将对其进行解释,而不会在输出中复制它。始终使用while IFS= read -r ...
。
bash
用一个简单的解释内容read
,那么bash
(再次)被破坏。原始shell中的read命令并没有废话。我认为POSIX shell不需要它。这会激怒我,bash
让您发现自己确实做到了—我已经与该程序建立了爱恨交织的关系,因为它在很多方面做得很好,但是有些事情做得不好,并且不断变化遗留行为是最糟糕的行为之一,并且要求启用旧的标准行为的选项非常烦人。看来你是对的;bash
很无聊!
residue
将从字段4(或更高版本)而不是字段3开始。
bash
它紧随POSIX2008 。我从不希望在超过四分之一世纪的Shell编程中使用该功能,但我想我应该很少。
仅使用外壳即可做到这一点
while read A B C; do
echo "$C"
done < oldfile >newfile
read -r
代替read
。
read -r
将保留反斜杠。read
将不会。例如:echo "foo ba\r"
将产生输出foo ba\r
。但是,echo "foo ba\r" | (while read first_column second_column; do echo "$second_column"; done)
将产生bar
与输出相同的结果(去掉反斜杠。添加-r
标记会产生正确的输出ba\r