如何从文件中删除列而不改变格式?

如何从文件中删除列而不改变格式?

我需要从这样的文件中删除第一列:

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的当前值重新生成,从而覆盖该行最初具有的格式。OFSSPACE

因此,如果您的输入文件是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 

相关内容