![如何从文件中删除列而不改变格式?](https://linux22.com/image/176079/%E5%A6%82%E4%BD%95%E4%BB%8E%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%A0%E9%99%A4%E5%88%97%E8%80%8C%E4%B8%8D%E6%94%B9%E5%8F%98%E6%A0%BC%E5%BC%8F%EF%BC%9F.png)
我需要从这样的文件中删除第一列:
165 1 chr22 42090593 0 1 chr22 42090609 1 42 42
166 1 chr22 42090593 0 1 chr22 42090654 1 42 42
167 1 chr22 42090595 0 1 chr22 42090633 1 42 42
168 0 chr22 42090612 0 1 chr22 42090656 1 42 42
169 0 chr22 42090614 0 0 chr22 42090617 1 40 42
170 0 chr22 42090647 0 1 chr22 42090749 1 42 42
171 1 chr22 42090684 0 1 chr22 42090692 1 42 42
172 1 chr22 42090733 0 1 chr22 42090743 1 42 42
173 1 chr22 42090733 0 1 chr22 42090775 1 42 42
174 1 chr22 42090733 0 1 chr22 42090789 1 42 42
175 1 chr22 42090757 0 1 chr22 42090787 1 42 24
176 0 chr22 42090778 0 0 chr22 42090790 1 42 42
177 0 chr22 42090800 0 0 chr22 42090802 1 42 42
178 0 chr22 42090803 0 0 chr22 42090806 1 42 42
命令
awk '{$1=""; print $0}'
正确删除第一列,但以这种方式改变格式
1 chr22 51178322 0 0 chr22 51178659 1 42 42
0 chr22 51178661 0 0 chr22 51178663 1 42 42
0 chr22 51178667 0 1 chr22 51178790 1 42 23
1 chr22 51178755 0 0 chr22 51178764 1 42 42
0 chr22 51178808 0 1 chr22 51178871 1 42 42
1 chr22 51178869 0 1 chr22 51178895 1 42 42
1 chr22 51178881 0 1 chr22 51178893 1 42 42
1 chr22 51178881 0 1 chr22 51178895 1 42 42
1 chr22 51179213 0 1 chr22 51179213 1 42 42
1 chr22 51180087 0 1 chr22 51180093 1 42 42
1 chr22 51180134 0 0 chr22 51181889 1 42 42
0 chr22 51186192 0 0 chr22 51186192 1 42 42
0 chr22 51186192 0 0 chr22 51186192 1 42 42
任何想法?
答案1
您的方法有两个问题。首先,这看起来像一个制表符分隔的文件,并且您没有告诉 awk 使用制表符。其次,当您在 awk 中设置字段时""
,您并没有删除该字段,而只是将其清空。所以它仍然被打印,这就是为什么你的输出中每行的开头都有一个额外的空格。
因此,如果您想在 awk 中执行此操作,则需要类似的内容(假设示例中的前导空格实际上不是文件的一部分):
$ awk -F"\t" 'BEGIN{OFS="\t"}{for(i=2;i<NF;i++){printf "%s%s",$i,OFS} print $NF}' file
1 chr22 42090593 0 1 chr22 42090609 1 42 42
1 chr22 42090593 0 1 chr22 42090654 1 42 42
1 chr22 42090595 0 1 chr22 42090633 1 42 42
0 chr22 42090612 0 1 chr22 42090656 1 42 42
0 chr22 42090614 0 0 chr22 42090617 1 40 42
0 chr22 42090647 0 1 chr22 42090749 1 42 42
1 chr22 42090684 0 1 chr22 42090692 1 42 42
1 chr22 42090733 0 1 chr22 42090743 1 42 42
1 chr22 42090733 0 1 chr22 42090775 1 42 42
1 chr22 42090733 0 1 chr22 42090789 1 42 42
1 chr22 42090757 0 1 chr22 42090787 1 42 24
0 chr22 42090778 0 0 chr22 42090790 1 42 42
0 chr22 42090800 0 0 chr22 42090802 1 42 42
0 chr22 42090803 0 0 chr22 42090806 1 42 42
但其他工具,比如cut
已经提到过这里更简单。如果您的文件是制表符分隔的,您可以这样做:
$ cut -f2- file
1 chr22 42090593 0 1 chr22 42090609 1 42 42
1 chr22 42090593 0 1 chr22 42090654 1 42 42
1 chr22 42090595 0 1 chr22 42090633 1 42 42
0 chr22 42090612 0 1 chr22 42090656 1 42 42
0 chr22 42090614 0 0 chr22 42090617 1 40 42
0 chr22 42090647 0 1 chr22 42090749 1 42 42
1 chr22 42090684 0 1 chr22 42090692 1 42 42
1 chr22 42090733 0 1 chr22 42090743 1 42 42
1 chr22 42090733 0 1 chr22 42090775 1 42 42
1 chr22 42090733 0 1 chr22 42090789 1 42 42
1 chr22 42090757 0 1 chr22 42090787 1 42 24
0 chr22 42090778 0 0 chr22 42090790 1 42 42
0 chr22 42090800 0 0 chr22 42090802 1 42 42
0 chr22 42090803 0 0 chr22 42090806 1 42 42
其他一些替代方案:
$ grep -oP '^\s*\S+\s*\K.*' file
1 chr22 42090593 0 1 chr22 42090609 1 42 42
1 chr22 42090593 0 1 chr22 42090654 1 42 42
1 chr22 42090595 0 1 chr22 42090633 1 42 42
0 chr22 42090612 0 1 chr22 42090656 1 42 42
0 chr22 42090614 0 0 chr22 42090617 1 40 42
0 chr22 42090647 0 1 chr22 42090749 1 42 42
1 chr22 42090684 0 1 chr22 42090692 1 42 42
1 chr22 42090733 0 1 chr22 42090743 1 42 42
1 chr22 42090733 0 1 chr22 42090775 1 42 42
1 chr22 42090733 0 1 chr22 42090789 1 42 42
1 chr22 42090757 0 1 chr22 42090787 1 42 24
0 chr22 42090778 0 0 chr22 42090790 1 42 42
0 chr22 42090800 0 0 chr22 42090802 1 42 42
0 chr22 42090803 0 0 chr22 42090806 1 42 42
或者
$ perl -pe 's/^\s*\S+\s*//' file
1 chr22 42090593 0 1 chr22 42090609 1 42 42
1 chr22 42090593 0 1 chr22 42090654 1 42 42
1 chr22 42090595 0 1 chr22 42090633 1 42 42
0 chr22 42090612 0 1 chr22 42090656 1 42 42
0 chr22 42090614 0 0 chr22 42090617 1 40 42
0 chr22 42090647 0 1 chr22 42090749 1 42 42
1 chr22 42090684 0 1 chr22 42090692 1 42 42
1 chr22 42090733 0 1 chr22 42090743 1 42 42
1 chr22 42090733 0 1 chr22 42090775 1 42 42
1 chr22 42090733 0 1 chr22 42090789 1 42 42
1 chr22 42090757 0 1 chr22 42090787 1 42 24
0 chr22 42090778 0 0 chr22 42090790 1 42 42
0 chr22 42090800 0 0 chr22 42090802 1 42 42
0 chr22 42090803 0 0 chr22 42090806 1 42 42
或者
$ perl -F'\t' -lane 'print join "\t",@F[1..$#F]' file
1 chr22 42090593 0 1 chr22 42090609 1 42 42
1 chr22 42090593 0 1 chr22 42090654 1 42 42
1 chr22 42090595 0 1 chr22 42090633 1 42 42
0 chr22 42090612 0 1 chr22 42090656 1 42 42
0 chr22 42090614 0 0 chr22 42090617 1 40 42
0 chr22 42090647 0 1 chr22 42090749 1 42 42
1 chr22 42090684 0 1 chr22 42090692 1 42 42
1 chr22 42090733 0 1 chr22 42090743 1 42 42
1 chr22 42090733 0 1 chr22 42090775 1 42 42
1 chr22 42090733 0 1 chr22 42090789 1 42 42
1 chr22 42090757 0 1 chr22 42090787 1 42 24
0 chr22 42090778 0 0 chr22 42090790 1 42 42
0 chr22 42090800 0 0 chr22 42090802 1 42 42
0 chr22 42090803 0 0 chr22 42090806 1 42 42
答案2
如果您有空格作为分隔符,这可能会起作用:
sed 's/^ *//' text.file | cut -f1 -d" " --complement
答案3
假设事实上有没有前导空格在您的文件中,以下sed
基于 - 的方法应该有效:
sed -r 's/^[[:digit:]]+[[:blank:]]+//' input_file
或者,更一般(如@terdon建议)
sed -r 's/^[^[:blank:]]+[[:blank:]]+//' input_file
第一个示例将从行的开头开始用“无”替换一个或多个数字,后跟一个或多个空白字符,从而删除该行的这一部分而不更改其余部分。
第二个示例删除任何“非空白”字符,后跟一个或多个空白字符,因此如果第一列还可以包含文本(例如在标题行中),则第二个示例更普遍适用。
如果有前导空格,则修改如下:
sed -r 's/^[[:blank:]]*[^[:blank:]]+[[:blank:]]+//' input_file
应该可以解决这个问题,因为它允许删除模式以在开头包含零个或多个空格。
请注意,它将[[:blank:]]
匹配空格和制表符,因此它也应该适用于制表符分隔的文件格式。
作为一般说明,使用时格式的更改awk
通常是由于未能设置输出字段分隔符 OFS
到适当的值。如果您修改awk
规则中的任何单个字段,这将导致使用默认值$0
的当前值重新生成,从而覆盖该行最初具有的格式。OFS
SPACE
因此,如果您的输入文件是TAB
- 分隔的,则修改任何字段都将导致输出以空格分隔,这可以解释您所描述的格式的变化。您可以通过设置适当的内部变量来克服这个问题
awk -v OFS='\t' '{你的代码在这里}' 输入文件
为了防止这种情况发生,但正如@terdon已经提到过,简单地将字段设置为空字符串并不会删除它,并且最终会得到不必要的附加字段分隔符。
答案4
您可以使用 gnu sed 来完成此操作
$ sed -Ee 's/\S+/\n&/2;s/.*\n//' file
我们标记第二个字段的开头,然后删除其之前的所有内容。
与上面的方法相同,但使用 awk
awk '
BEGIN {
s = "[[:space:]]"; S = "[^[:space:]]"
F = S"+"s"*"
}
sub(s"*" F, "")+1
' file
与上面相同的方法,但具有匹配功能
awk '
BEGIN {
s = "[[:space:]]"; S = "[^[:space:]]"
F = S"+"s"*"
}
match($0, F) {
$0 = substr($0, RSTART+RLENGTH)
}1
' file