我file1
包含多个制表符分隔的字段,其中我只想删除包含特定字符串的字段,在我的例子中是下划线字符_
(不删除所有行):
cat file1
357M 2054_
357_ 154= 1900_
511_ 419X 1481_ 34=
我想获得以下信息:
cat file2
357M
154=
419X 34=
我设法删除了这些字段,如下所示:
cat file1 | perl -pe 's/\w+_\s*//g'
357M 154= 419X 34=
但格式不好,因为我不想改变列数。
我也尝试过:
cat file1 | sed 's/[0-9]*_//g'
357M
154=
419X 34=
但我想去掉那些空列。
一种实际上也有效的蛮力方法:
cat file1 | sed 's/[0-9]*_//g' | tr -s '\t' '\t' | sed 's/^[ \t]*//g'
357M
154=
419X 34=
最后一条命令: (1) 删除所有包含下划线的字段; (2) 将一行中的多个选项卡替换为一个选项卡; (3) 删除前导标签。虽然不是那么优雅。
有什么建议么?
答案1
考虑:
sed 's/[^\t]*_//; s/\t[^\t]*_/\t/g' < input
这执行两个(条件)替换:
- 第一个表示“任何(零个或多个)非制表符后跟下划线”,替换为“(无)”
- 第二个表示“将制表符后跟任何(零个或多个)非制表符后跟下划线”替换为“制表符”,并在找到该搜索模式时多次执行此操作。
需要进行第一次搜索,以便找到应删除的前导字段;第二个扫除其余的。
这会将原始字段保留在其列中:
357M
154=
419X 34=
要完全删除字段,只需在搜索和替换文本中包含选项卡即可:
sed 's/[^\t]*_\t//; s/\t[^\t]*_//g' < input
结果是:
357M
154=
419X 34=
答案2
你可以使用这个简单的sed
.
sed 's/\w*_\s*//;/^$/d' infile.txt
/^$/d
将删除空行,其中该行仅包含一个以下划线foo_
或_
单独结尾的字段。
给出结果:
357M
154=
419X 34=
答案3
总是有“蛮力和无知”的方法。
- 去掉坏字段
- 将多个选项卡转换为单个选项卡
- 从行首删除单个标签
- 从行尾删除单个选项卡
它不聪明,不聪明,但它有效。
在下文中,TAB 表示文字 TAB 字符
sed -e 's/[0-9]*_//g' -e 's/TABTAB/TAB/g' -e 's/^TAB//' -e 's/TAB$//'
例如
$ cat x
357M 2054_
357_ 154= 1900_
511_ 419X 1481_ 34=
$ sed -e 's/[0-9]*_//g' -e 's/ / /g' -e 's/^ //' -e 's/ $//' < x
357M
154=
419X 34=
答案4
如果您只关心内部字段(即,不是一行中的第一个或最后一个字段)。但您想查看所有领域。所以我有一个解决方案,让它看起来我们没有处理每行的最后一个字段:
sed -e 's/$/\t/' -e 's/[^\t]*_[^\t]*\t//g' -e 's/\t$//'
这
- 在每行末尾添加一个制表符(从而实际上创建一个n+1 th 字段,该字段为空)。
- 查找包含 的所有字段(非制表符字符串)
_
并删除它们以及后面的制表符(将其替换为空)。这适用于n th 字段(即原始行的最后一个字段),因为步骤 1 在末尾添加了一个制表符。 - 从行尾删除多余的制表符。
它具有保留空字段的功能(我知道您没有要求,但一旦您看到它可用,您可能会感激):
$ 猫文件3 棕色的狗跳了起来。 敏捷的狐狸胜过懒惰的狐狸 四年又_年 七年前的分数... $(上面的命令)文件3 棕色的狗跳了起来。 敏捷的狐狸胜过懒惰的狐狸 四年 七年前的分数...
PS 根据sed
您所使用的版本,您可能需要在命令中输入实际的选项卡而不是\t
.或者,如果您使用的是 bash,则可以$'…'
使用sed
包含\t
.