2009-04-27 5 views
5

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

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

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

J

ответ

23

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

Как вы объясните, команда `cat named.local | Grep зона»дает выход немного, как это:

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

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

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

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

Я не уверен, что вы знакомы с Regular Expressions, но они являются бесценным инструментом для любого человека, пишущего сценарии оболочки. Например, регулярное выражение /.o.e/ будет соответствовать любой строке, где есть слово со второй буквой, это нижний регистр o, а четвертый - 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 - вставить содержимое первой группы (то, что было в круглых скобках) совпала.
  • / - конец регулярного выражения

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

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

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

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

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

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

Таким образом, вся команда горя ÜLD быть что-то вроде:

cat named.local | grep zone | sed -e "s/^.*\"\(.*\)\".*$/\"\1\"/" 
+0

Yup, я использую его прямо сейчас, но я думаю, что должен быть более простой способ сделать это, потому что теперь я использую sed -e 's/zone "// g' | sed -e 's /" { // g ', чтобы удалить начало и конец файла, а не просто совместить середину. – jpou

+1

Бритье от начала и конца вполне приемлемо. Это не соревнование - если это сработает, все в порядке. Если вы хотите сделать это, сопоставляя текст в кавычках, взгляните на «группы захвата». – zoul

+0

ugh. Я слишком долго набирал это, и это все еще не сделано ... Кажется, меня всех избили. Но я рад, что вы уже поняли это :-) – scraimer

1

1.

[email protected]:etc$ cat named.conf | grep zone 
zone "." IN { 
zone "localhost" IN { 
    file "localhost.zone"; 
zone "0.0.127.in-addr.arpa" IN { 

2.

[email protected]:etc$ cat named.conf | grep ^zone 
zone "." IN { 
zone "localhost" IN { 
zone "0.0.127.in-addr.arpa" IN { 

3.

[email protected]: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. Когда вы «помните» что-то в регулярном выражении, используя parens, вы можете напомнить его как \1, \2 и т. Д. Запутайтесь с ним какое-то время.

2

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

% grep '^zone' /etc/bind/named.conf | cut -d' ' -f2 
"gennic.net" 
"generic-nic.net" 
"dyn.generic-nic.net" 
"langtag.net" 
0

Пока кто-то указывая на СЭД/AWK, я собираюсь укажите, что grep избыточен.

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

Это дает вам то, что вы ищете без кавычек (перемещайте кавычки в скобках, чтобы сохранить их).В AWK, это еще проще с цитаты:

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

Я стараюсь избегать трубопроводов как можно больше (но не более). Помните, Don't pipe cat. Это не нужно. И, так же, как awk и sed, дублирующие работу grep, также не печатайте grep. По крайней мере, не в sed или awk.

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

Смежные вопросы