Передача части узоров из седа в оболочку - PullRequest
5 голосов
/ 29 января 2012

У меня есть файл, который содержит строки следующего формата:

w1 # 1 # x w2 # 4 # b w3 # 2 # d ...

Каждое слово (токен) в строке (например, w1 # 1 # x) состоит из 3 частей, первая показывает некоторый индекс (в данном случае w1), вторая представляет собой целое число (в данном случае 1), и третий символ (x в данном случае)

Теперь для каждого слова (токена) мне нужно напечатать дополнительное поле, которое будет рассчитываться на основе значения второй и третьей части (, т.е. , 4-я часть будет функцией 2-й и 3-я часть), и выходной файл должен выглядеть так:

w1 # 1 # x # f1 w2 # 4 # b # f2 w3 # 2 # d # f3 ...

, где

f1 = функция (1, x), f2 = функция (4, b), f3 = функция (2, d)

Теперь, используя шаблоны sed, я могу идентифицировать компоненты в каждом слове (токене), например,

echo $ line | sed "s / ([^ #] ) # ([^ #] ) # ([^ #] *) / \ 1 # \ 2 # \ 3 / g"

где \ 2 и \ 3 - части шаблона (я называю их частями шаблона из-за этой ссылки )

Теперь мне нужно вычислить 4-ю часть, используя \ 2 и \ 3. Я определил функцию оболочки getInfo (), которая принимает 2 аргумента, выполняет необходимые вычисления и возвращает 4-ю часть. Проблема заключается в вставке этой функции в команду sed. Я попробовал следующее:

echo $ line | sed "s / ([^ #] ) # ([^ #] ) # ([^ #] *) / \ 1 # \ 2 # \ 3`getInfo \ 2 \ 3` / g"

но это не работает. Оболочка не получает частей шаблона в качестве аргументов.

Итак, вопрос:

Как передать sed части шаблона в оболочку (функция)?

Я легко могу написать сценарий оболочки, который разбил бы строку на слово и выполнил бы требуемую работу, а затем сшил файл обратно, но я был бы очень признателен, если бы оболочка могла получить частей шаблона в качестве аргументов от sed внутри команды sed.

С уважением,

Салил Джоши

Ответы [ 2 ]

6 голосов
/ 29 января 2012

Это может работать для вас:

func(){ echo "$1#$2#$3#$2$3"; }
export -f func
echo "w1#1#x w2#4#b w3#2#d" |
sed 's/\([^#]*\)#\([^#]*\)#\([^ ]*\) \?/echo -n "$(func \1 \2 \3) "; /g;s/$/echo ""/' |
sh
w1#1#x#1x w2#4#b#4b w3#2#d#2d 

Или, если у вас есть GNU sed:

func(){ echo "$1#$2#$3#$2$3"; }
export -f func
echo "w1#1#x w2#4#b w3#2#d" |
sed 's/\([^#]*\)#\([^#]*\)#\([^ ]*\) \?/echo -n "$(func \1 \2 \3) "; /ge;s/.$//'
w1#1#x#1x w2#4#b#4b w3#2#d#2d
3 голосов
/ 29 января 2012

Наступает момент, когда sed больше не является правильным инструментом для задания . Я думаю, что эта задача достигла этой точки (но см. Умный ответ по potong , который показывает, что это можно сделать с bash и sed).

Какой альтернативный инструмент вы используете? Вы не показываете функцию, но если ее удобно вычислить в оболочке с помощью функции оболочки, есть вероятность, что awk достаточно мощный, чтобы выполнить эту работу. Я бы, вероятно, остановился на Perl, но Python (или Ruby) также будет работать хорошо. Все это позволяет вам написать функцию, прочитать данные и применить функцию к данным, прежде чем записывать данные обратно.

Проблема с попыткой использования функции в sed заключается в том, что у нее нет механизма для определения функций или выполнения функций оболочки. Чтобы использовать sed, вам нужно подумать о двух проходах по данным: сначала извлекать (уникальные) токены для последующей обработки, то есть применять функцию оболочки к каждому токену, генерируя сценарий sed, который просто сопоставляет каждый токен и заменяет его заменой, а затем применяет этот сценарий во втором проходе данных.

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