这可能是一个非常基本的问题,但我无法形成适用于此的sed on liner。
考虑这一行:
foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291
我希望将从“@”到空格之间的所有内容替换为逗号分隔。因此,我的预期输出应该如下:
foo,bar,xyz
我尝试使用
sed -e 's/@.*[^ ]/,/g'
命令将内容替换为空格,但它会替换整行(在编写正则表达式时不是很好)。如果有帮助,将不胜感激。在@
字符之前,您可以找到并捕获除了@
以外的任何1个或多个字符,然后匹配@
和任何0个或多个非空格字符,后跟0个或多个空格字符,并将所有这些替换为占位符到组1和逗号。然后,您需要删除尾随逗号。
请查看sed演示:
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/,$//'
sed 's/\([^@][^@]*\)@[^[:space:]]*[[:space:]]*/\1,/g'
代替POSIX ERE版本。在BRE POSIX中,您应该转义(
和)
以形成捕获组,并且+
量词应该被转义,或者用aa*
结构替换。
详细信息
([^@]+)
- 捕获组1:除@
外的1个或多个字符@
- @
字符[^[:space:]]*
- 除空格外的0个或多个字符[[:space:]]*
- 0个或多个空格字符\1
是捕获组#1捕获的文本的占位符。sed 's/,$//'
用于删除字符串末尾的逗号,
。awk
可以帮助您解决这个问题。awk 'BEGIN{OFS=","}{for(i=1;i<=NF;i++){sub(/@.*/,"",$i)}} 1' Input_file
解决方案2:采用Wiktor Stribizew帖子中的代码并稍作修改,将其转换为单个sed
。
sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g;s/,$//' Input_file
awk
,sed
解决方案;-) +1!看起来我回答这个问题有点晚了,哈哈 - Allan即使这样做可能有点复杂,但你也可以采用另一种方法。
$ 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 '(?=,|^)[^@]+'
获取@
之前的所有内容。它使用带有lookaround的perl正则表达式(强制约束前一个字符是逗号或字符串的开头,并接受除@
之外的所有字符)。tr -d '\n'
用于删除grep
插入的EOL。\n
,则可以省略echo ""
。然后,您可以简化命令:tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'
.*
在第一个 @
后面几乎匹配了源字符串的整个剩余部分(这是非常常见的错误),而 [^ ]
则匹配最后一个非空格字符。@\S+\s*
作为匹配部分,那么 \S+
将匹配 "非空格" 部分(例如 some_text/48183
),而 \s*
将匹配之后的可选空格。foo,bar,xyz,
,所以你需要删除最后一个逗号。sed 's/@\S*\s/,/g;s/@\S*//' file
就足够了。 - potong
sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g' | sed 's/,$//'
命令。 - Wiktor Stribiżew