#awk #sed
Вопрос:
У меня есть формат файла, как показано ниже,
####################### FILE Content ###################
Path 1
AND cell
OR1 cell
BUFF1 cell
OR2 cell
Ends
Path 2
OR1 cell
BUFF1 cell
AND1 cell
AND2 cell
BUFF2 cell
OR2 cell
Ends
Path 3
AND1 cell
AND2 cell
AND3 cell
OR1 cell
Ends
##########################################
Мне нужен вывод, как показано ниже:
Path 1 - BUFF* count 1
Path 2 - BUFF* count 2
Path 3 - No BUFF
Используя sed, я могу сначала создать шаблон, подобный шаблону.
sed -n '/Path/,/Ends/p'
Далее, чтобы получить выход после этого, мне нужна ваша экспертная помощь.
кто-нибудь может мне помочь, пожалуйста.
Спасибо, ГБ
Ответ №1:
Вы можете использовать awk
и использовать шаблоны, чтобы проверить, находитесь ли вы между путем, за которым следует цифра, и концами.
Когда он совпадет Ends
, выведите текущий путь, по которому вы находитесь, и количество БАФФОВ.
Затем сбросьте видимые переменные и бафф.
awk '
/^Path [0-9] /{seen=1; buff=0; path=$0; next}
{
if(seen amp;amp; $1 ~ /^BUFF[0-9] $/){ buff;}
}
{
if(seen amp;amp; $1 ~ /^Ends$/){
print path " - " (buff ? "BUFF* count " buff : "No BUFF")
seen=0; buff=0
}
}
' file
Выход
Path 1 - BUFF* count 1
Path 2 - BUFF* count 2
Path 3 - No BUFF
Ответ №2:
С вашими показанными образцами, попытайтесь; пожалуйста, попробуйте выполнить следующий код awk
.
awk '
/Path/{
if(count){
print pathVal," - BUFF* count "(count?count:"NO BUFF")
}
found=""
count=0
pathVal=$0
next
}
/BUFF/{
count
}
/Ends/{
found=1
}
END{
if(found){
print pathVal," - BUFF* count "(count?count:"NO BUFF")
}
}
' Input_file
Пояснение: Добавление подробного объяснения вышеизложенного.
awk ' ##Starting awk program from here.
/Path/{ ##If line contains Path then do following.
if(count){ ##If count is set then do following.
print pathVal," - BUFF* count "(count?count:"NO BUFF") ##Printing output with variables and string as per OP need here.
}
found="" ##Nullifying found here.
count=0 ##Setting 0 to count here.
pathVal=$0 ##Setting current line to pathVal here.
next ##next will skip all further statements from here.
}
/BUFF/{ ##Checking if BUFF is found in line then increase count with 1 here.
count
}
/Ends/{ ##Checking if Line contains Ens then setting found to 1 here.
found=1
}
END{ ##Starting END block of this program from here.
if(found){ ##If found is set then print as per OP requirement values with strings.
print pathVal," - BUFF* count "(count?count:"NO BUFF")
}
}
' Input_file ##Mentioning Input_file name here.
Комментарии:
1. Но, конечно, это здорово. Я потратил некоторое время на то, чтобы собрать его вместе, поэтому я подумал, что давайте опубликуем это. Я забыл о
next
звонке, поэтому добавил его.
Ответ №3:
Это может сработать для вас (GNU sed и оболочка):
sed -n '/^Path.*/{s//amp; - BUFF* count $((0))/;h}
/^BUFF/{g;s/(0/(0 1/;h}
/^Ends/{g;/ /!s/-.*/- No BUFF/;s/^Path.*/echo "amp;"/ep;z;h}' file
Для каждого Path
сделайте копию, добавьте немного текста и инициализируйте счетчик.
Для каждого BUFF
приращения используется счетчик.
Для каждого Ends
из них замените добавленный текст другим текстом , если счетчик не был увеличен. Заключите все сообщение в двойные кавычки и повторите результат путем оценки результата, а затем очистите его.
N. B. Счетчик будет интерполирован в двойных кавычках команды echo.
Ответ №4:
С awk
в режиме абзаца и использованием gsub()
функции для определения того, сколько раз /BUFF[[:digit:]] /
появляется:
awk -v RS= -v FS='n' '
$1 ~ /Path/ amp;amp; $NF == "Ends" amp;amp; /BUFF/{
n=gsub(/BUFF[[:digit:]] /,"amp;");print $1 " - BUFF* count " n}
$1 ~ /Path/ amp;amp; $NF == "Ends" amp;amp; !/BUFF/{
print $1 " - No BUFF"}
' file
Path 1 - BUFF* count 1
Path 2 - BUFF* count 2
Path 3 - No BUFF