[РЕШЕНО] awk - печать только 1 вхождения для нескольких равных шаблонов

vasek
indeviral, Dobrov отсылает к своему файлу … и не хочет пояснить … но, насколько я понимаю, местоположение строки переменно (меняется в зависимости от соотвествующего тэга/запроса), и простой командой вряд ли обойдешься.
Чтобы построить алгоритм необходимо четко представлять всю эту кухню, а так одни гадания …. но могу и ошибаться.
Я чётко в нескольких постах расписал задачу - печатать между двумя строками (шаблонами) произвольный текст, игнорируя повторное совпадение шаблонов.
vasek
нужно определять еще и номер строки, имеюшей тэг END …
Вот это кстати не проблема.
cat test | grep -m2 -n <my tag>
Но тут есть нюанс может в этих строках после тэга что-то будет, тогда не сработает.
Хотя можно вывести строки с номера до номера вместе с тэгами, а уже потом их убрать...
Dobrov
Я чётко
Вы молодец. Но в целом не понятно((
Ошибки в тексте-неповторимый стиль автора©
Вообщем за красотой не гнался, важна была конечная цель, просто проверить - написал скриптик, как описывал выше (но для варианта 1-ой строки между тэгами BEGIN/END)
- читаем построчно файл, включаем счетчик, доходим до строки с BEGIN и вычисляем номер следующей строки, выводим эту строку и выходим.
~/test.sh
Tag text
Если строка не одна, придется добавлять условие и вычислять номер строки с тэгом END … и выводить строки, находящиеся между вычисленными номерами.
Скрипт не привожу - заклюют, самому не очень нравится.
PS - Имхо, red, знаток awk, проделал бы это более изящно.
Ошибки не исчезают с опытом - они просто умнеют
В awk не знаю, а для sed получилось, что-то не читаемое, но на вашем примере рабочее
[anode@TM-8481 ~]$ sed -n $(($(sed -n '/BEGIN<my tag>/=' mytagtest | sed -n 1p)+1)),$(($(sed -n '/END<my tag>/=' mytagtest | sed -n 1p)-1))p mytagtest
        Tag text
anode
не там немного сложнее, он дальше уже другой пример привёл...

#!/bin/bash
declare file=$1
tag='<my tag>'
num=$(grep -m2 -n "$tag" "$file" | grep -o '[[:digit:]]*' | xargs)
seds(){
  sed -n $(($1 + 1)),$(($2 - 1))p $file
}
seds $num
Ошибки в тексте-неповторимый стиль автора©
Или так:
[anode@TM-8481 ~]$ sed -n '{/BEGIN/,/END/p};/END/q' mytagtest | sed '1d;$d'
        Tag text
indeviral, да как бы поставленной задаче соответствует:
Dobrov
Задача: извлечь из тела скрипта $0 текст между двумя шаблонами, исключая сами шаблоны и используя только первое вхождение:
Я не писал полностью /^# BEGIN<my tag>... Тот вариант, что приводит Dobrov
Dobrov
sed -n '/^# BEGIN<my tag.*/,/^# END<my tag.*/p' $0| sed '1d;$d'
надо чучуть поправить до
[anode@TM-8481 ~]$ sed -n '{/^# BEGIN<my tag.*/,/^# END<my tag.*/p};/^# END<my tag.*/q' mytagtest | sed '1d;$d'
И на примере файла mytagtest

# BEGIN<my tag>
        Tag text
4444444444444444444444
4444444444444444444444
55555555555frfrfrfrfrf
w   r45rf4fftftgyg  66
# END<my tag>
# BEGIN<my tag>
        Tag text 2222
4444444444444444444444
4444444444444444444444
55555555555frfrfrfrfrf
w   r45rf4fftftgyg  66
# END<my tag>

rrrrrrrrrrrrrrrrrrrrrr
tttttttttttttttttttttt
tttttttttttttttttttttt
rrrrrrrrrrrrrrrrrrrrrr
# BEGIN<my tag>
        Random Tag match…
# END<my tag>
результат вроде тот, что надо, или я не понял
[anode@TM-8481 ~]$ sed -n '{/^# BEGIN<my tag.*/,/^# END<my tag.*/p};/^# END<my tag.*/q' mytagtest | sed '1d;$d'
        Tag text
4444444444444444444444
4444444444444444444444
55555555555frfrfrfrfrf
w   r45rf4fftftgyg  66
anode
да как бы поставленной задаче соответствует:
ну да, вроде то что надо.
Ошибки в тексте-неповторимый стиль автора©
Всем спасибо, переделаю скрипт run (это комбайн для запуска часто используемых действий)
anode
sed -n '{/^# BEGIN<my tag.*/,/^# END<my tag.*/p};/^# END<my tag.*/q' mytagtest | sed '1d;$d'
Всегда вызывает восторг, когда смотрю на сложную конструкцию команды, собранной с использованием awk или sed
Просто сам это использую редко и только в простых конструкциях - ... ну такова специфика работы, использую другое ... а потому, чтобы написать такую конструкцию понадобится несколько часов (минимум полдня) - пока вспомнишь, почитаешь DOC, протестируешь (с 1-го раза никогда не получается) ...
Но подвернулся хороший случай и решил устроить экзамен своим молодым хакерам ... понадобилось им на написание скрипта bash около 10 часов. Логику они просекли сразу, но вот над выводом нужных строк помучались долго - то вывод был пустой, то несколько строк были объединены в одну, то отсутствовала буква n ... вообщем урок получили хороший. В итоге родился следующий скрипт ... привожу просто для сравнения с конструкцией на основе sed (вместо одной строки куча строк - зато понятно)
1. Сам скрипт
cat ~/teg.sh
#!/bin/bash
read -p "Указываем начальный тэг: " T1
read -p "Указываем конечный   тэг: " T2
echo "................................."
tmpIFS=$IFS; IFS='\r'
count=0
cat ~/teg.txt | (
   while read line;  do
      count=$((count+1))
      if [[ "$line" == *"$T1"* ]]; then
          N=$(echo $count)
          elif [[ "$line" == *"$T2"* ]]; then
               M=$(echo $count)
              ST=$(awk -v "num1=$N" -v "num2=$M" 'num1 < NR && NR <num2' ~/teg.txt)
              echo $ST
              exit
      fi
  done
)
IFS=$tmpIFS
exit 0
2. Обрабатываемый файл
cat ~/teg.txt
11111111111111111111
2222222222222222
33333333333
# BEGIN<my tag>
        Tag text
		…
	end text
4444444444444444444444
4444444444444444444444
55555555555frfrfrfrfrf
w   r45rf4fftftgyg  66
# END<my tag>
# BEGIN<my tag>
        Tag text 2222
4444444444444444444444
4444444444444444444444
55555555555frfrfrfrfrf
w   r45rf4fftftgyg  66
# END<my tag>
3. Результат применения скрипта
~/teg.sh
Указываем начальный тэг: BEG
Указываем конечный   тэг: END
.................................
        Tag text
		…
	end text
4444444444444444444444
4444444444444444444444
55555555555f f f f f f
w    45 f4fftftgyg  66

PS - осваивайте awk и sed ...
Ошибки не исчезают с опытом - они просто умнеют
 
Зарегистрироваться или войдите чтобы оставить сообщение.