Bash получая линии между двумя шаблонами и редактируя их

У меня есть вывод команды dumpsys, и я хочу извлечь строки между двумя шаблонами, Wake Locks и newline. После того, как я получу эти строки, мне нужна определенная строка из них. Wake и Lock появляются в выходных данных более одного раза, но Wake Locks: размер только один раз, поэтому первый шаблон может быть "Wake*Locks*size"

Вывод выглядит примерно так (theres много строк выше и ниже этого)

Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
WAKELOCK 'Term' (uid=35647, pid=362505, ws=null)
#White space

Я хочу строки между "Wake Locks: size=*" и следующей новой строкой, в формате, который я могу извлечь из него pids. Может быть, что-то вроде этого:

for i in `dumpsys power | #Some way to get the desired lines#`; do
Temp=`echo $i | awk '{print $4}'`
$Temp #Assign var pid = number
kill -9 $pid
done

ОБНОВИТЬ

Обновленный код:

dumpsys power | 
sed -n '/Wake Locks: size=/,/^$/ p' |
sed -e 's/.*pid=\([0-9]*\).*/\1/' | 
while read pid; do
    kill -9 ${pid}
done

4 ответа

Решение

Когда у вас нет совпадений в первой строке, будет делать sed (вы можете проверить первую строку первой).
Сначала удалите все строки перед Wake Locks (и этой строкой), затем удалите все из первой пустой строки в оставшемся потоке, и, пока вы уже выполняете синтаксический анализ, получите pid (с помощью (\ а также \) вы получите запомненную строку, значение которой напечатано \1).

dumpsys power | sed -e '1,/Wake Locks: size=3/ d' \
                    -e '/^$/,$ d' \
                    -e 's/.*pid=\([0-9]*\).*/\1/' | while read pid; do
   echo "You want to kill ${pid}"
done

РЕДАКТИРОВАТЬ:
Извините, sed можно использовать с флагом -n: sed -n '/Wake Locks: size=3/,/^$/p',
Таким образом, вы можете переписать код на более естественный

dumpsys power | 
   sed -n '/Wake Locks: size=3/,/^$/ p' |
   sed -e 's/.*pid=\([0-9]*\).*/\1/' | 
   while read pid; do
      echo "You want to kill ${pid}"
   done

awk в помощь!

$ awk '/Wake Locks: size=/{f=1} !NF{f=0} f' file

дам тебе

Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
WAKELOCK 'Term' (uid=35647, pid=362505, ws=null)

если вам нужны только значения pid (есть три, какое?), вы можете попробовать это

awk -v FS="[ ,]" 'f{for(i=1;i<=NF;i++) 
                       if($i~/pid=/) {
                           sub(/pid=/,"",$i);print $i
                        }
                   } 
/Wake Locks: size=/{f=1} 
                !NF{f=0}' file     
364345
323345
362505

Объяснение: Установите флаг f с шаблоном и не устанавливайте, когда пустая строка (NF: количество полей = 0). Если флаг установлен, итерация по полям и при совпадении шаблона удаляют шаблон, чтобы оставить искомое число). Разделитель поля устанавливается на пробел и запятую, чтобы удалить суффикс запятой из числа с разделителем по умолчанию. Вы можете использовать результаты в while read pid; do ... done < <(awk ...) или трубопровод к другому сценарию, который может обрабатывать многострочный ввод.

Если я понимаю строки, которые вы хотите извлечь правильно, вы можете сделать то же самое с помощью встроенных команд bash (расширение параметра / извлечение подстроки):

#!/bin/bash

## read from "$1" or stdin
[ -r "$1" ] && infile="$1" || infile=/dev/stdin

## check line beginnings for each line
while read -r line; do
    [ "${line%%:*}" = "Wake Locks" -o \
    "${line%% *}" = "WAKELOCK_NAME" -o \
    "${line%% *}" = "ANOTHER_WAKELOCK" -o \
    "${line%% *}" = "WAKELOCK_NAME" ] && echo "$line"
done < "$infile"

exit 0

Или используя grep Вы можете использовать файл, содержащий шаблоны, которые вы хотите сопоставить в вашем файле большего размера и вызвать grep -f matchfile largefile, Файл соответствия в этом случае может выглядеть так:

файл шаблона grep

$ cat dat/wakematch.txt
^Wake Locks:
^WAKELOCK_NAME
^ANOTHER_WAKELOCK
^WAKELOCK_NAME

Тестовый ввод

$ cat dat/wake.txt
junk and more junk

Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
WAKELOCK 'Term' (uid=35647, pid=362505, ws=null)
#White space

junk and more junk

Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
WAKELOCK 'Term' (uid=35647, pid=362505, ws=null)
#White space

Use/Output - расширение параметра bash / извлечение подстроки

$ bash wakelock.sh dat/wake.txt
Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)

$ bash wakelock.sh <dat/wake.txt
Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)

Используя grep

$ grep -f dat/wakematch.txt dat/wake.txt
Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)
Wake Locks: size=3
WAKELOCK_NAME  'Term' (uid=93847, pid=364345, ws=null)
ANOTHER_WAKELOCK 'Term' (uid=9190247, pid=323345, ws=null)

Использование gawk

gawk '{if($0~/Wake Locks:/){while( !($0~/^\n$/) && getline >=1){print gensub(/.*pid=([0-9]+).*/,"\\1",$0);}}};'

выход

364345
323345
362505
Другие вопросы по тегам