Как сопоставить точную строку с помощью `sed`? Но не часть этого.


8

У меня есть входной файл FILE1.TXT, как показано ниже.


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

Я хочу найти все поля, принадлежащие определенному идентификатору, и получить значение NAME

Мне удалось перебрать каждый Id и сформировать команду ниже для каждого Id по мере необходимости.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

Проблема в том, что я получаю вывод NAME1 , в дополнение к этому я также получаю NAMEXYZ .

Что нужно изменить, чтобы я получил только NAME1, но не NAMEXYZ ?

В качестве обходного пути работают следующие команды.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

Есть ли «переключатель» или я что-то упустил?

Ответы:


3

Если вы знаете номера строк, которые хотите найти (как подсказывает ваша буква Q), затяните регулярное выражение, чтобы вы не соответствовали нежелательным строкам.

Например, изменить:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

в

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

Значение ^будет соответствовать началу строки и пробелу после числа гарантирует, что конкретный номер строки будет совпадать, и вы не будете обрабатывать ненужные блоки.


Это помогло бы. Но как я могу соответствовать ^(random no of spaces)11?
Vinay

1
@VinayChalluru использоватьsed -n '/^\s*11 /,/^\s*14 /p'
Кейси

1
это может быть короткая рука sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' , вы пробовали это?
Рахул Патил

@RahulPatil Да, это работает.
Vinay

6

Используйте границы слов:

grep '\bNAME1\b'

будет соответствовать, NAME1а не NAME1XYZили XYZNAME1.

По аналогии,

sed -n '/11\b/,/14\b/p'

не будет соответствовать строки, содержащие 111и 142.


РЕДАКТИРОВАТЬ: Кажется, что числа во входном файле на самом деле являются номерами строк. Если это так, вы можете просто сказать:

sed '11,14!d'

чтобы получить нужные строки.


Между NAMEстроками 11 и 14 есть только одна . Итак, почему sedсмотрит на 111и 114? Как сделать так, чтобы он не смотрел между 111и 114?
Vinay

@VinayChalluru Смотрите ответ выше, чтобы узнать, как вы можете изменить sedвыражение.
devnull

Это ответ на мой вопрос, я думаю. Позвольте мне попробовать и дать вам знать.
Vinay

для границ слова, grepс -wфлагом? не так ли?
Рахул Патил

1
@RahulPatil Да, для приведенного выше примера -wбудет эквивалентным. Для sedпримера -wнемного отличается.
devnull

4

Вы можете использовать AWK

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

Это будет выглядеть строки между 13 до 17, затем искать имя и, если совпадение, то будет печатать последнее слово из Name = LastWord


Когда я пытаюсь это сделать, я получаю сообщение об ошибке, в котором говорится, что номер строки ввода должен быть меньше 199.
Vinay

@VinayChalluru можете ли вы показать мне вывод с помощью команды, используйте paste.ubuntu.com
Рахул Патил

Извиняюсь. Я добавил $ранее, NRи это вызвало ошибку.
Vinay

@VinayChalluru Все нормально. Это хорошо, что вы попробовали / проверили каждый ответ и узнали что-то новое ..: D
Рахул Патил

Точно. Там намного больше впереди. :-)
Vinay

4

Вам не нужен никакой другой инструмент для этого, sedон легко справится с этим.

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

Это должно предоставить вам только первую последовательность непробельных символов после фразы «NAME =» для каждой строки, в которой эта фраза находится между строками 11 и 14 любого входного файла sed.


3

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

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename

Не могли бы вы объяснить вторую и третью строку вашей команды awk?
Эрик

0

универсальная версия, не основанная на номере строки, но ссылка на идентификатор

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. загрузить весь файл
  2. чистый раздел не входит в группу id (рекурсивно)
  3. просто примите значение NAME в группе
  4. распечатать результат

0

Вы можете напечатать те строки, которые содержат соответствующий шаблон, используя sed следующим образом:

sed -n '/pattern/p'  Filename
  • -n- эти опции отключают эту автоматическую печать, и sed выдает выходные данные только при явном указании pкоманды.

  • p - Распечатать

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.