使用带有两个不同分隔符的 cut/awk/sed

使用带有两个不同分隔符的 cut/awk/sed

我有以下案例:

 [email protected]
 [email protected]
 [email protected]

我正在尝试将这些转换为

 [email protected]
 [email protected]
 [email protected]

所以它应该删除从第一个“_”(包括它)到@(不包括它)的所有内容。

我有一些东西,但它并不能真正正常工作:

基于此线程:一次性基于两个分隔符进行剪切,以及此 U&L 问答:按第一次出现的分隔符分割字符串

sed 's/^.*_\([^ ]*\) .*\@\([^$]*\)$/\1 \2/' infile

但没有运气。有人想敲响它吗?

答案1

不确定你到底在做什么,但你可以这样做sed

$ sed 's/\(case\).*\(@test.com\)/\1\2/' 87529.txt 
[email protected]
[email protected]
[email protected]

这有效地修剪了case和之间的所有内容@

您可以执行类似的操作awk

$ awk -F@ '{split($1,a,"_"); print a[1]"@"$2}' 87529.txt 

也可以通过以下方式完成perl(类似于evisoup的方法):

$ perl -p -e 's/_.*@/@/g' 87529.txt 

或者你可以利用perl的前瞻设施:

$ perl -p -e 's/_.*(?=@)//g' 87529.txt 

笔记:Lookahead 和 Lookbehindperl允许您将字符串包含在要匹配的正则表达式模式中,而无需将它们包含在将针对正则表达式执行的操作中。将它们视为插入符号 ( ^) - 行的开头和美元 ( $) - 行的结尾的动态版本。@与删除后必须将其添加回来相比,这有点不那么麻烦。

答案2

假设你不会有超过一个@符号,

sed 's/_.*@/@/' file.txt

...应该管用。

答案3

如果你的 shell 支持参数扩展,你可以这样做

while read line; do
    printf "%s\n" "${line%%_*}@${line#*@}"
done < your_file_here

扩展${line%%_*}会删除最左边的内容_及其后面的所有内容,而扩展${line#*@}会删除最左边的内容@及其前面的所有内容。

答案4

邪恶汤的 解决方案似乎很完美!

另一种解决方案同时使用sedawk

sed 's/_/ /g; s/@/ /g' file_name | awk '{ print $1"@"$NF '}

这对于效率来说并不完全重要,但是当人们不想弄乱正则表达式时,也许很容易理解。上面的代码执行以下操作:

  • 第一个模式sed用空白替换“_”。
  • 的第二个模式sed将“@”替换为空格。所以,现在我们将文件的内容分成多列:

案例 test.com
案例 1_2 test.com
案例 1 test.com

  • 最后,awk简单地打印分隔内容的第一列和最后一列。这里,NF是一个特殊符号,awk表示一行中的字段数。

相关内容