У меня есть текстовый файл в следующем формате:
keyword value
keyword value
...
Где ключевое слово - это одно слово, а значение - это все остальное до конца строки. Я хочу прочитать файл из сценария оболочки таким образом, чтобы значения (но не ключевые слова) подвергались расширению оболочки.
С помощью sed легко сопоставлять ключевые слова и значимые части
input='
keyword value value
keyword "value value"
keyword `uname`
'
echo "$input"|sed -e 's/^\([^[:space:]]*\)[[:space:]]\(.*\)$/k=<\1> v=<\2>/'
который производит
k=<keyword> v=<value value>
k=<keyword> v=<"value value">
k=<keyword> v=<`uname`>
но тогда возникает вопрос, как я могу встроить команду оболочки в заменяющую часть выражения sed. В этом случае я бы хотел, чтобы замена была \1 `echo \2`
.
Ответы:
Стандартный sed не может вызывать оболочку ( GNU sed имеет расширение для этого) , если вы заботитесь только о не встроенном Linux), поэтому вам придется выполнять некоторую обработку вне sed. Есть несколько решений; все требуют тщательного цитирования.
Непонятно, как именно вы хотите, чтобы значения были расширены. Например, если строка
какой из следующих выводов должен быть?
Я расскажу о нескольких возможностях ниже.
чистая оболочка
Вы можете заставить оболочку читать строку ввода построчно и обрабатывать ее. Это самое простое решение, а также самое быстрое для коротких файлов. Это самое близкое к вашему требованию «
echo \2
»:read -r keyword value
задает$keyword
первое разделенное пробелами слово строки, а$value
остальной части строки минус конечный пробел.Если вы хотите расширить ссылки на переменные, но не выполнять команды вне подстановок команд, поместите их
$value
в документ здесь . Я подозреваю, что это то, что вы действительно искали.седь по трубам
Вы можете преобразовать ввод в сценарий оболочки и оценить его. Сед справляется с задачей, хотя это не так просто. Следуя вашему
echo \2
требованию « » (обратите внимание, что нам нужно избегать одинарных кавычек в ключевом слове):Переходя к документу здесь, нам все еще нужно экранировать ключевое слово (но по-другому).
Это самый быстрый метод, если у вас много данных: он не запускает отдельный процесс для каждой строки.
AWK
Те же самые методы, которые мы использовали с sed, работают с awk. Полученная программа значительно более читабельна. Идем с «
echo \2
»:Используя здесь документ:
источник
Имея GNU,
sed
вы можете использовать следующую команду:Какие выводы:
с вашими входными данными.
Объяснение:
Команда sed подавляет обычный вывод с помощью
-n
опции.-r
передается для использования расширенных регулярных выражений, что спасает нас от некоторых специальных символов в шаблоне, но это не требуется.Команда
s
используется для передачи строки ввода в команду:Ключевое слово get указывает значение not. Я передаю опцию
e
- специфичную для GNU -s
команде, которая говорит sed выполнять результат подстановки как команду оболочки и считывать ее результаты в буфер шаблонов (даже в несколько строк). Использование опцииp
after (!)e
Приводит кsed
печати буфера шаблонов после выполнения команды.источник
-n
иp
варианты , то естьsed -r 's/([^ ]+) (.*)/echo "\1" \2\n/e' input
. Но спасибо за это! Я не знал об этомe
варианте.e
варианта (введенного GNU). Это все ещеsed
? :)Вы можете попробовать этот подход:
(если я правильно понял ваше намерение). То есть вставьте «process» в начале каждой непустой строки, чтобы сделать его похожим на скрипт:
быть оцененным (
eval
) где процесс - это функция, которая печатает ожидаемое сообщение.источник
Если приемлемо решение, не относящееся к sed, этот фрагмент PERL сделает эту работу:
источник
ТОЛЬКО ЧИСТЫЙ ЧИСТЫЙ САД
я сделаю это
и это работает.
источник