Сценарий оболочки: заменить соответствующий текст на вывод программы - PullRequest
1 голос
/ 27 ноября 2010

Я хочу заменить определенные строки в текстовом потоке выводом программы, запущенной на этих строках. Например, замените любое вхождение "# filename #" на вывод identify filename

Есть ли простой способ сделать это?

Ответы [ 2 ]

3 голосов
/ 27 ноября 2010

Предполагая, что 'identify filename' сама по себе является командой, тогда я думаю, что для этого вам понадобится Perl.В лучшем непроницаемом для Perl стиле:

while (<>)
{
     s/#(\w+)#/my $x = qx%identify $1%; chomp $x; $x/e;
     print;
}

Это читает строку ввода ('<>') в неявную переменную '$_';следующая строка применяет операцию замены к неявной переменной - больше подробностей в данный момент - и затем 'print' печатает неявную переменную.

Что касается операции замены 's///', перваяpart ищет хеш «#», серию из одного или нескольких символов «слово» - буквенно-цифровые или подчеркивания - и другой хеш, делая указанное имя файла доступным как «$1».Вторая часть - это строка замены.После третьей косой черты следует модификатор «e», который означает «выполнить замену как бит Perl».И соответствующий бит Perl:

my $x = qx%identify $1%; chomp $x; $x

Первая часть выполняет команду 'identify filename', если строка между хеш-метками - «имя файла», сохраняя вывод, новую строку и все в локальномпеременная $ х.Операция 'chomp' удаляет символ новой строки;последний '$x' возвращает значение - строку, которая была выведена командой 'identifier'.(К моему удивлению, Perl не позволяет выглядеть более просто: s/#(\w+)#/chomp qx%identify $1%/e; ошибка была 'Can't modify quoted execution (``, qx) in chomp at xx.pl line 3, near "qx%identify $1%)"'.)

Рассмотрим команду 'identifier':

echo "identified file $1 as $PWD/$1"

Теперь рассмотрим строку ввода:

abc#def#ghi

Вывод:

abcidentified file def as /Users/jleffler/tmp/soq/defghi

(где /Users/jleffler/tmp/soq оказался моим текущим каталогом при выполнении команды).

Скорее менее непонятно:

while (my $line = <>)
{
    if ($line =~ m/#(\w+)#/)
    {
        my $identity = qx{identify $1};
        chomp $identity;
        $line =~ s/#\w+#/$identity/;
    }
    print $line;
}

Конечно, не так компактно, но объяснение очень похоже.

Обратите внимание, что первоначальное издание - не самая компактная из возможных форм.Рассмотрим следующую версию:

perl -p -e 's/#(\w+)#/my $x = qx%identify $1%; chomp $x; $x/e'

Опция '-p' помещает скрипт (аргумент '-e') в цикл чтения, выполнения, печати (REPL).

Этоодно из чудес Perl - TMTOWTDI (произносится «тим-тоади») - есть больше, чем один способ сделать это.

0 голосов
/ 27 ноября 2010
REPLACEMENT=`identify filename`
sed "s/#filename#/$REPLACEMENT/g"

РЕДАКТИРОВАТЬ: см. Комментарий Деннис Уильямсон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...