Здравствуйте!Есть некий файл вида:
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 работает?
Спасибо!
>Здравствуйте!
>
>Есть некий файл вида:
>
>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^/
>echo и "обратные кавычки" нейтрализуют друг друга. собсно команде echo передается в
>качестве аргумента \1, буквально. она его выводит, и обратными кавычками \1
>"возвращается" в команду sed. т.е. после того, как шелом обработана "вставка"
>`echo __'\1'__` выполняется команда
>sed "s/This is address \([0-9A-F]*\)/__\1__/" file1Точно! Спасибо большое, что-то меня клинануло :)