我有一个包含很多行的文件。每行以一个模式开始gi_[0-9]
,紧接着是一个制表符,之后是一个单词列表,所有单词都用分号分隔。我只想保留最后 8 个单词(7 个部分,因为最后一个部分有 2 个单词)。
这是一个例子输入文件:
gi_1\tDog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2\tPork;Black;White;Beige;Brown;Cyan;Purple;Red pepper
这相应的输出应该:
gi_1\tPink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2\tBlack;White;Beige;Brown;Cyan;Purple;Red pepper
笔记:我没有找到插入制表符的方法,所以我写了 \t 代替,但是我的文件中有制表标记。
答案1
短的sed方法:
sed 's/^\(.*\t\)[^;]*;/\1/' file
输出:
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
\(.*\t\)
- 捕获第一部分所需的部分
答案2
和awk
:
awk -F '\t' -v OFS='\t' 'sub("^[^;]*;", "", $2)' file.txt
sub("^[^;]*;", "", $2)
将子字符串替换为;
从制表符分隔的 (-F '\t'
) 第二个字段开始到第一个的子字符串为 null。sub()
是否更换到位-v OFS='\t'
将输出字段分隔符设置为制表符第一个字段(以及其他所有字段)保持原样
为了完整起见,请确保第一个字段gi_
后跟一个数字:
awk -F '\t' -v OFS='\t' '$1 ~ /^gi_[[:digit:]]$/ {sub("^[^;]*;", "", $2); print}' file.txt
例子:
% cat file.txt
gi_1 Dog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Pork;Black;White;Beige;Brown;Cyan;Purple;Red pepper
% awk -F '\t' -v OFS='\t' 'sub("^[^;]*;", "", $2)' file.txt
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
% awk -F '\t' -v OFS='\t' '$1 ~ /^gi_[[:digit:]]$/ {sub("^[^;]*;", "", $2); print}' file.txt
gi_1 Pink;Blue;Beige;Yellow;Orange;Red;Green irish
gi_2 Black;White;Beige;Brown;Cyan;Purple;Red pepper
答案3
使用带有 Perl 风格的 grep 的通用解决方案:
$ a="gi_1 \t Dog;Pink;Blue;Beige;Yellow;Orange;Red;Green irish"
[s@SS data]$ echo $a | grep -P -o "((^gi_. \\\t )|(?<=[; ])(?:.(?!(([; ].+)){8}))+$)" | sed ':a;N;$!ba;s/\n/ /g'
gi_1 \t Pink;Blue;Beige;Yellow;Orange;Red;Green irish
请注意,这适用于任意数量的单词。
非捕获组和负向先行排除不遵循重复序列 [; 的任何字符。 ] 后跟任意字符。
开头的正向前瞻摆脱了前导的 [; \t] 字符
sed 部分去掉了中间的新行。
答案4
使用 GNU sed,我们可以通过在 do-until 循环结构中查找 6 个分号来完成此操作。
sed -e '
:loop
s/\t[^;]*;/\t/
s/;/&/6
Tloop
' yourfile