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