如何在替换模式中将`sed`匹配推送到shell调用?

时间:2010-05-01 16:54:13

标签: sed

我需要在文本文件中替换多个URL,其中一些内容取决于URL本身。让我们说简单一点,它就是URL上文档的第一行。

我正在尝试的是:

sed "s/^URL=\(.*\)/TITLE=$(curl -s \1 | head -n 1)/" file.txt

这不起作用,因为未设置\1。但是,shell被调用了。我可以以某种方式将sed匹配变量推送到该子流程吗?

4 个答案:

答案 0 :(得分:4)

接受答案是完全错误的。证明:

制作可执行文字foo.sh

#! /bin/bash

echo $* 1>&2

现在运行它:

$ echo foo | sed -e "s/\\(foo\\)/$(./foo.sh \\1)/"
\1
$ 

在运行 sed 之前,$(...)已展开

答案 1 :(得分:3)

所以你试图从sed替换的替换模式中调用外部命令。我不认为它可以完成,模式中的$ ...只允许你使用已经存在的(常量)shell变量。

我选择Perl,请参阅search-replace运算符中的/ e选项(s /.../.../)。

UPDATE :我错了,sed很好地使用了shell,它可以让你做到这一点。但是,\1中的反弹应该被转义。请尝试改为:

sed "s/^URL=\(.*\)/TITLE=$(curl -s \\1 | head -n 1)/" file.txt

答案 2 :(得分:1)

试试这个:

sed "s/^URL=\(.*\)/\1/" file.txt | while read url; do sed "s@URL=\($url\)@TITLE=$(curl -s $url | head -n 1)@" file.txt; done

如果原始文件中存在重复的URL,则输出中将有n ^ 2个URL。 @作为分隔符取决于不包括该字符的URL。

答案 3 :(得分:0)

迟到的回复,但确保人们不会被这里的答案所抛弃 - 这个可以使用{{1>在 gnu sed 中完成命令。例如,以下代码在行的开头递减一个数字:

e

将产生:

echo "444 foo" | sed "s/\([0-9]*\)\(.*\)/expr \1 - 1 | tr -d '\n'; echo \"\2\";/e"