соответствующий текст в кавычках (новичок) - PullRequest
5 голосов
/ 27 апреля 2009

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

context: у меня есть файл named.conf, и мне нужны все имена зон в простом файле для дальнейшей обработки. Так что я делаю ~ $ cat named.local | Зона grep и совершенно потерялись здесь. Мой вывод ~ сто или около того новых строк в форме 'zone "domain.tld" {', и мне нужен текст в двойных кавычках.

Спасибо, что показали способ сделать это.

J

Ответы [ 5 ]

23 голосов
/ 27 апреля 2009

Я думаю, что вы ищете sed ... это s tream ed итор, который позволит вам делать замены построчно .

Как вы объясняете, команда `cat named.local | grep zone 'дает вам вывод, похожий на этот:

zone "domain1.tld" {
zone "domain2.tld" {
zone "domain3.tld" {
zone "domain4.tld" {

Я предполагаю, что вы хотите, чтобы вывод был примерно таким, поскольку вы сказали, что вам нужен текст в двойных кавычках:

"domain1.tld"
"domain2.tld"
"domain3.tld"
"domain4.tld"

Итак, на самом деле, из каждой строки мы просто хотим, чтобы текст был заключен в двойные кавычки (включая сами двойные кавычки).

Я не уверен, что вы знакомы с Регулярными выражениями , но они являются бесценным инструментом для любого человека, пишущего сценарии оболочки. Например, регулярное выражение /.o.e/ будет соответствовать любой строке, где есть слово, где 2-я буква была в нижнем регистре o, а 4-я была e. Это будет соответствовать строке, содержащей такие слова, как "zone", "tone" или даже "I am tone-deaf."

Хитрость заключалась в том, чтобы использовать символ . (точка) для обозначения «любой буквы». Есть пара других специальных символов, таких как *, что означает «повторить предыдущий символ 0 или более раз». Таким образом, регулярное выражение типа a* будет соответствовать "a", "aaaaaaa" или пустой строке: ""

Таким образом, вы можете сопоставить строку внутри кавычек, используя: /".*"/

Есть еще одна вещь, которую вы знаете о sed (и по комментариям, вы уже делаете!) - она ​​позволяет возврат . Как только вы скажете ему, как распознать слово, вы можете использовать его как часть замены. Например, предположим, что вы хотите включить этот список:

Billy "The Kid" Smith
Jimmy "The Fish" Stuart
Chuck "The Man" Norris

В этот список:

The Kid
The Fish
The Man

Сначала вы искали строку внутри кавычек. Мы уже видели это, это было /".*"/.

Далее мы хотим использовать то, что находится внутри кавычек. Мы можем сгруппировать с помощью паренов: /"(.*)"/

Если бы мы хотели заменить текст на кавычки подчеркиванием, мы бы сделали замену: s/"(.*)"/_/, и это оставило бы:

Billy _ Smith
Jimmy _ Stuart
Chuck _ Norris

Но у нас есть возвращение! Это позволит нам вспомнить, что было внутри паренов, используя символ \1. Так что если мы сделаем сейчас: s/"(.*)"/\1/ мы получим:

Billy The Kid Smith
Jimmy The Fish Stuart
Chuck The Man Norris

Поскольку кавычек не было в скобках, они не были частью содержимого \1!

Чтобы оставить только содержимое в двойных кавычках, нам нужно сопоставить всю строку. Для этого у нас есть ^ (что означает «начало строки») и $ (что означает «конец строки».)

Так что теперь, если мы используем s/^.*"(.*)".*$/\1/, мы получим:

The Kid
The Fish
The Man

Почему? Давайте прочитаем регулярное выражение s/^.*"(.*)".*$/\1/ слева направо:

  • s/ - Запустить подстановку регулярное выражение
  • ^ - Ищите начало строки. Начните оттуда.
  • .* - Продолжайте читать, читая каждый символ, пока ...
  • " - ... пока вы не достигнете двойной кавычки.
  • ( - создать группу символов, которую мы могли бы вспомнить позже при возврате.
  • .* - Продолжайте читать, читая каждый символ, пока ...
  • ) - (pssst! Закрыть группу!)
  • " - ... пока вы не достигнете двойной кавычки.
  • .* - Продолжайте читать, читая каждый символ, пока ...
  • $ - Конец строки!

  • / - используйте то, что после этого, чтобы заменить то, что вы выбрали

  • \1 - вставить содержимое первой группы (что было в скобках), совпадающее.
  • / - конец регулярного выражения

Проще говоря: «Прочитайте всю строку, скопировав текст между двойными кавычками. Затем замените всю строку содержимым между двойными кавычками».

Вы можете даже добавить двойные кавычки вокруг заменяющего текста s/^.*"(.*)".*$/"\1"/, так что мы получим:

"The Kid"
"The Fish"
"The Man"

И это может быть использовано sed для замены строки содержимым из кавычек:

sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"

(Это просто экранирование, чтобы иметь дело с двойными кавычками, косой чертой и прочим.)

Так что вся команда будет выглядеть примерно так:

cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/"
2 голосов
/ 27 апреля 2009

Ну, никто еще не упомянул cut, поэтому, чтобы доказать, что есть много способов сделать что-то с оболочкой:

% grep '^zone' /etc/bind/named.conf  | cut -d' ' -f2
"gennic.net"
"generic-nic.net"
"dyn.generic-nic.net"
"langtag.net"
1 голос
/ 27 апреля 2009

1.

zoul@naima:etc$ cat named.conf | grep zone
zone "." IN {
zone "localhost" IN {
    file "localhost.zone";
zone "0.0.127.in-addr.arpa" IN {

2

zoul@naima:etc$ cat named.conf | grep ^zone
zone "." IN {
zone "localhost" IN {
zone "0.0.127.in-addr.arpa" IN {

3.

zoul@naima:etc$ cat named.conf | grep ^zone | sed 's/.*"\([^"]*\)".*/\1/'
.
localhost
0.0.127.in-addr.arpa

регулярное выражение .*"\([^"]*\)".*, что соответствует:

  1. любое количество любых символов: .*
    • цитата: "
    • начинает помнить на потом: \(
    • любые символы, кроме цитаты: [^"]*
    • заканчивает группу для запоминания: \)
    • закрывающая цитата: "
    • и любое количество символов: .*

При вызове sed синтаксис 's/what_to_match/what_to_replace_it_with/'. Одиночные кавычки предназначены для того, чтобы ваше регулярное выражение не было расширено на bash. Когда вы «запомнили» что-то в регулярном выражении с помощью паренов, вы можете вспомнить это как \1, \2 и т. Д. Немного поиграть с этим.

0 голосов
/ 27 апреля 2009

Пока кто-то указывает на sed / awk, я хочу отметить, что grep является избыточным.

sed -ne '/^zone/{s/.*"\([^"]*\)".*/\1/;p}' /etc/bind/named.conf

Это дает вам то, что вы ищете без кавычек (переместите кавычки в круглые скобки, чтобы сохранить их). В awk это даже проще с кавычками:

awk '/^zone/{print $2}' /etc/bind/named.conf

Я стараюсь избегать трубопроводов как можно больше (но не больше). Помните, Не трубите, кошка . Это не нужно. И, так как awk и sed дублируют работу grep, также не отправляйте grep по конвейеру. По крайней мере, не в sed или awk.

Лично я бы, наверное, использовал perl. Но это потому, что я, вероятно, сделал бы все остальное, что вы делаете в Perl, сделав это незначительной деталью (и имея возможность вбрасывать весь файл и одновременно проверять все, игнорирование \ n было бы бонусом в случаях, Я не контролирую / etc / bind, например, на общем веб-хосте). Но если бы я делал это в оболочке, я бы подошел к одному из двух вышеупомянутых способов.

0 голосов
/ 27 апреля 2009

Вы должны взглянуть на awk .

...