Как мне вставить `sed` совпадения в вызов оболочки в шаблоне замены? - PullRequest
1 голос
/ 01 мая 2010

Мне нужно заменить несколько URL-адресов в текстовом файле содержимым, зависящим от самого URL-адреса. Допустим, для простоты это первая строка документа по URL.

Что я пытаюсь это:

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

Это не работает, поскольку \1 не установлено. Однако оболочка вызывается. Можно ли как-то передать переменные sed в этот подпроцесс?

Ответы [ 4 ]

4 голосов
/ 09 октября 2012

Принять ответ просто неправильно. Доказательство:

Создать исполняемый скрипт foo.sh:

#! /bin/bash

echo $* 1>&2

Теперь запустите:

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

$(...) расширяется до запуска sed .

3 голосов
/ 01 мая 2010

Итак, вы пытаетесь вызвать внешнюю команду из шаблона замены подстановки sed. Я не думаю, что это можно сделать, $ ... внутри шаблона просто позволяет вам использовать уже существующую (постоянную) переменную оболочки.

Я бы пошел с Perl, см. Параметр / e в операторе search-replace (s /.../.../ e).

ОБНОВЛЕНИЕ : Я был не прав, sed прекрасно играет с оболочкой, и это позволяет вам делать это. Но тогда, обратная реакция в \1 должна быть исключена. Попробуйте вместо:

sed "s/^URL=\(.*\)/TITLE=$(curl -s \\1 | head -n 1)/" file.txt
1 голос
/ 01 мая 2010

Попробуйте это:

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-адресов, не включающих этот символ.

0 голосов
/ 30 августа 2017

Поздний ответ, но при этом нужно убедиться, что люди не будут сбиты с толку ответами здесь - это можно сделать в gnu sed с помощью команды e. Следующее, например, уменьшает число в начале строки:

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

даст:

443 foo
...