使用sed在新行上获取匹配字符串



我正在尝试使用sed在新行上获取匹配的非数字字符串

所以,如果我有字符串abc def 123 (ghi),我希望输出为:

(abc)
(def)
(ghi)

这就是我尝试过的:

echo "abc def 123   (ghi)" | sed -r 's/([a-z]+)/(1)n/g'

但这输出如下:

(abc)
(def)
123   ((ghi)
)  

我在这里很困惑。有很多疑问:为什么2号线和3号线有领先空间?为什么使用双括号ghi?为什么123没有被消除?为什么,最后一行单独出现了封闭的苦咸水湖?

更新

实际上,我想从特定的域中提取URL。因此,使用评论和答案中的建议,我尝试了以下内容:

in="https://www.example.com/user1 ddsf none  http://www.example.com/user2 kbu7f7yy"
echo $in | sed 's/http[s]*://www.example.com/[^ ]*/&n/g'

打印如下:

https://www.example.com/user1
ddsf none http://www.example.com/user2
kbu7f7yy

所以,我尝试了这个(如一个中所建议的(

echo $in | sed 's/.*(http[s]*://www.example.com/[^ ]*).*/1n/g'

但我最终得到了:

http://www.example.com/user2

) (替换行首、字母和行尾之间的任何内容,然后删除多余的括号:

sed -r 's/[^a-z]+|^|$/) (/g;s/^) | ($//g'

但我发现以下Perl解决方案更可读:

perl -lne 'print "($1)" while /([a-z]+)/g'
  • -n逐行读取输入并为每行运行代码
  • -l从输入中删除换行符并将其添加到输出中

这可能对你有用(GNU sed(:

sed -E '/n/!s/<[[:alpha:]]+>/n(&)n/g;/^([[:alpha:]]+)/P;D' file

这会在paren中用换行符包围alpha字符串,然后只打印以打开paren、alpha字符和关闭paren开头的行。

对于url,可能是:

sed -E '/n/!s/https?S+/n&n/g;/^https?/P;D' file

使用-E命令行选项以便使用扩展的regexps:

  • /n/!s/https?S+/n&n/g如果当前行不包含任何换行符,则全局替换以http开头的字符串,并用可选的s替换换行符包围的同一字符串
  • /^https?/P如果当前图案空间的前面以带有可选shttp开始,则打印到并包括下一新行
  • 如果模式空间不为空,D将删除下一个新行,并重新启动sed循环(不从文件中获取下一行(

因此,将进行第一次替换,然后进行打印/删除。每次处理时,图案空间都会减少,直到它为空,然后下一行将呈现给图案空间。

sed可以很简单:sed 's/[()0-9]//g; s/[a-z]+/(&)n/g; s/ //g;'
  • 删除所有括号和数字
  • 环绕(&)n中的所有单词,其中&是匹配单词的简写
  • 删除所有空格

也可以这样做:grep -Pow '[a-z]+' | sed 's/.*/(&)/'

对于url示例,grep比sed更容易提取单词:grep -Pow 'httpS+'

  • 用于perl匹配的-P允许S+表示"非空间">
  • -o仅用于匹配
  • 用于单词匹配的-w(相当于bhttpS+b(

如果出于某种原因仍要添加parens,grep -Pow 'httpS+' | sed s/.*/(&)/

最新更新