У меня есть большой файл больше чем с 5 000 строк в следующем формате
Ниже отрывка показывает два блока файла.
string name : abcd
used :metric
test :ok
{
fun: add
fun: sub
fun: mul
fun: div
}
string name : degh
used: non -metric
test: good
{
fun: per
fun: div
fun: add
fun: mul
}
То, в чем я нуждаюсь, должно искать string name
(например: abcd
), и затем распечатайте значения после fun :
от этого string name
блок
Я хотел бы следующий вывод:
abcd add
abcd sub
abcd mul
abcd div
degh per
degh div
degh add
degh mul
Каков был бы надлежащий способ решить эту проблему?
#!/bin/bash
RE_NAME='^ *string name *:' # regex for the 'name' line
RE_FUNSTART='^ *[{] * Bash может быть немного медленным для больших файлов. Если это слишком медленно для Вас, Вы могли бы портировать код на, например, Perl или Python.
# regex for the start of the 'fun' block
RE_FUNEND='^ *[}] * Bash может быть немного медленным для больших файлов. Если это слишком медленно для Вас, Вы могли бы портировать код на, например, Perl или Python.
# regex for end of 'fun' block
RE_FUN='^ *fun:' # regex for 'fun' line
while read line; do
if [[ $line =~ $RE_NAME ]]; then
name="${line##*: }"
echo
elif [[ $line =~ $RE_FUNSTART ]]; then
fun='1'
elif [[ $line =~ $RE_FUNEND ]]; then
fun=''
elif [[ ($line =~ $RE_FUN) && (-n $fun) ]]; then # match 'fun' lines only inside 'fun' block
echo "$name ${line##*: }"
fi
done < your_big_file
Bash может быть немного медленным для больших файлов. Если это слишком медленно для Вас, Вы могли бы портировать код на, например, Perl или Python.
Другой подход с awk:
awk '{ if ($1 == "string") name = $4; else if ($1 == "fun:") print name " " $2; }' your_file
Предположение, которые" string name
" и" :
" разделяются пространством и" fun
", всегда сопровождается" :
" без пространства.
Один из способов приблизиться к нему с жемчугом:
$ perl -lane '$hold=$F[3] if $_ =~ "^string name.*";print "$hold $F[1]" if $F[0] eq "fun:"' bigfile.txt
abcd add
abcd sub
abcd mul
abcd div
degh per
degh div
degh add
degh mul