>Здравствуйте! > >Есть некий файл вида: > >file1: >===================================== >This is address 000075AF >String 1 >String 2 >This is address 0000753D >String 1 >String 2 >... >===================================== > >Есть также другой файл, в котором адресам сопоставлены имена: > >file2: >===================================== >Name1 000075AF >Name2 0000753D >... >===================================== > >Требуется преобразовать первый файл file1, заменить там адреса на имена. >Должно получиться такое: >===================================== >Name1 >String 1 >String 2 >Name2 >String 1 >String 2 >===================================== > >В общем-то, это не проблема. Но я сейчас пробую изучить возможности sed >и вопрос возник такой: возможно-ли сделать это командой sed в одну >строку? Вопрос чисто теоретический, призванный глубже понять возможности sed. > >В общем-то, в редакторе sed есть команда s///, которая заменяет одно на >другое. Во второй части команды можно поставить "\1", означающее найденную часть. > >Поэтому, к примеру, выделение адреса тривиально: > >sed "s/This is address \([0-9A-F]*\)/\1/" file1 > out > >Пусть есть некий элементарный скрипт, выполняющий поиск во втором файле и возвращающий >имя: > >script: >===================================== >#!/bin/sh >grep $1 file2 | awk '{print $1}' >===================================== > >Теперь попробуем подставить во вторую часть результат выполнения этого скрипта: >sed "s/This is address \([0-9A-F]*\)/`./script '\1'`/" file1 > out > >Получаем ошибку: "grep: invalid back reference" > >В то же время какое-нибудь элементарное эхо работает вполне прилично: >sed "s/This is address \([0-9A-F]*\)/`echo __'\1'__`/" file1 > out > >Получается вот что: >===================================== >__000075AF__ >String 1 >String 2 >__0000753D__ >String 1 >String 2 >... >===================================== > >В идеале должно получиться нечто такое: >sed "s/This is address \([0-9A-F]*\)/`grep '\1' file2 | awk '{print $1}'`/" file1 > out > >Пожалуйста, проконсультируйте по вышеописанному. Почему grep не работает, а echo работает? >Спасибо! echo и "обратные кавычки" нейтрализуют друг друга. собсно команде echo передается в качестве аргумента \1, буквально. она его выводит, и обратными кавычками \1 "возвращается" в команду sed. т.е. после того, как шелом обработана "вставка" `echo __'\1'__` выполняется команда sed "s/This is address \([0-9A-F]*\)/__\1__/" file1 и вы видите вроде бы правильный результат. но он неправильный. ибо echo не имела своим аргументом текст, соответствующий \1, а имела лишь строку \1 буквально. данная команда запускает целый набор процессов, и одним из них является шел, эту команду запустивший. именно шел делает все подстановки по ``. тем не менее про то, что делает sed он не знает, и не имеет доступа к его контексту. а эквивалент для \1 существует лишь в контексте sed. советую почитать таки man sh (man bash) на тему выяснения, какую именно (немаловажную) роль играет шел в выполнении подобных конструкций. и четко уяснить как именно и какие данные передаются между процессами - участниками при использовании конструкций ``, | (пайплайн), eval итд.\^P^/
|