sed多次重新排列

时间:2018-06-04 07:24:42

标签: regex sed

这可能是一个非常基本的问题,但我无法为此制作衬垫。

考虑这一行

foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291

我想将所有内容从“@”替换为以逗号分隔的空格。 所以我的预期输出应该是

foo,bar,xyz

我正在尝试sed -e 's/@.*[^ ]/,/g'替换直到空间,但是它正在替换整行(在编写常规exp时不太好)。

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

您可以在@字符之前找到并捕获除@之外的任何1个字符,然后匹配@以及除空格之外的任何0 +字符,后跟0 +空白字符,并将占位符替换为组1和逗号。然后,您将不得不删除尾随的逗号。

查看sed demo

s='foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291'
echo "$s" | sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g' | sed 's/,$//'

请注意,您也可以使用POSIX ERE版本的sed 's/\([^@][^@]*\)@[^[:space:]]*[[:space:]]*/\1,/g'内容。在BRE POSIX中,您应该转义()以形成捕获组,+量词应该被转义,或者用aa*构造替换。

<强>详情

  • ([^@]+) - 捕获第1组:除@以外的其他字符
  • @ - @字符
  • [^[:space:]]* - 除了空格之外的0个字符
  • [[:space:]]* - 0+空白字符

\1是使用捕获组#1捕获的文本的占位符。

第二个sed 's/,$//'用于删除字符串末尾的尾随,

答案 1 :(得分:2)

关注awk可能会对您有所帮助。

awk 'BEGIN{OFS=","}{for(i=1;i<=NF;i++){sub(/@.*/,"",$i)}} 1'  Input_file

解决方案第二: 从Wiktor Stribizew的帖子中获取代码并进行一些修改,现在将其转换为单个sed

sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g;s/,$//'  Input_file

答案 2 :(得分:2)

正则表达式(@.*[^ ])的匹配部分的基本问题是.* 在第一个@之后几乎匹配源字符串的整个休息 (一个非常常见的错误)和[^ ]匹配最后一个非空格字符。

如果您使用@\S+\s*作为匹配部分,则\S+匹配&#34;非空格&#34;部分 (例如some_text/48183)和\s*此后匹配可选空格。

此替换提供foo,bar,xyz,,因此您应该以某种方式删除最后一个逗号。

答案 3 :(得分:2)

即使可能更多pipy,你也可以反过来做。

$ echo "foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291" | (tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'; echo "")
foo,bar,xyz

您可以直接提取相关部分,而不是替换部分字符串。

<强>说明:

  • tr ' ' ','以逗号替换所有空格。
  • grep -oP '(?=,|^)[^@]+'获取@之前的所有内容。它使用带有环视的perl正则表达式(强制约束前面的字符是逗号或字符串的开头,并接受除@之外的所有字符。
  • tr -d '\n'用于删除grep
  • 插入的EOL
  • 如果您不需要结尾echo "",则可以省略\n。然后,您可以在tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'
  • 中简化命令