Я пытаюсь найти здесь какой-нибудь предыдущий вопрос, который я мог бы использовать, но, к сожалению, не могу найти именно свой случай.
Я хотел бы получить вывод другой команды, который выглядит примерно так:
pattern.d
17.91
17.55
pattern.b
pattern.a
7.21
9.34
pattern.c
к этому:
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
Я попытаюсь объяснить немного больше: После каждой строки, содержащей строку "pattern", всегда должно быть число. Если нет, я хотел бы вставить новую строку со значением 1000.
Обратите внимание, что у шаблона есть «расширение» (.a .b .c .d, но в «расширении» нет цифр), которое меняется, и это поможет мне позже отсортировать содержимое в алфавитном порядке.
EDIT: Я принял ответ, но на случай, если кто-то все еще хочет поискать другой вариант, я должен указать, что встречаемость «шаблона» варьируется, и может быть более 2 или 3 последовательных вариантов, как в:
pattern.a
pattern.d
pattern.c
pattern.d
pattern.b
17.91
решение1
Вот sed
решение, которое будет работать с любыми входными данными (например, с несколькими последовательными строками, соответствующими pattern
):
sed '1{ # when on first line
x # exchange
s/^/1000/ # replace the empty hold buffer with "1000"
x # exchange back
}
: do # label "do"
/pattern/{ # if the current line matches "pattern"
${ # if we're on the last line
G # append hold buffer content to pattern space
b # go to end of script
}
n # otherwise print and pull in the next line
/^[[:digit:]]/!{ # if this one doesn't start with a digit
x # exchange
p # print (the pattern space is now "1000")
x # exchange back
b do # go to label "do"
}
}' infile
С gnu sed
ним можно записать как
sed '1{x;s/^/1000/;x};:b;/pattern/{${G;b};n;/^[[:digit:]]/!{x;p;x;bb}}' infile
Вы можете сделать что-то подобное с помощью awk
:
awk -vc=0 '!/^[[:digit:]]/{
if (c) {print "1000"}
}
{ if (/pattern/){c=1} else{c=0}
}
END{if (c){print "1000"}
};1' infile
то есть, установить c=1
на совпадающих строках pattern
и c=0
на остальных строках, а также на каждой строке, которая не начинается с цифры (а также в блоке END
), проверить, c
установлен ли (или 1
- что означает, что предыдущая строка совпадает pattern
) - если да, вывести 1000
.
решение2
sed -e '
$!{
/pattern\.[a-z]/N
/\n/!b
/\n[+-]\{0,1\}[.][0-9]\{1,\}$/b
/\n[+-]\{0,1\}[0-9]\{1,\}\([.][0-9]*\)\{0,1\}$/b
h;s/\(.*\n\).*/\11000/p
g;D
}
/pattern\.[a-z]/a\
1000
' yourfile
Полученные результаты
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
Работающий
- Пока мы не достигли конца файла,
$!{...}
мы добавляем следующую строку в пространство шаблона при условии, что текущая строка представляет интерес. - Затем мы пропускаем дальнейшую обработку в случаях: а) Не найдена новая строка => нет шаблона в текущей строке. б) Число с плавающей точкой формата .nnn во второй строке. в) Число с плавающей точкой формата mmm, mmm. или mmm.nnn найдено исключительно во второй строке. г) Исключая любую из возможностей => нам нужно добавить магическое число 1000 в конец следующей строки после новой строки.
решение3
Если никогда не встречается более двух последовательных экземпляров pattern
, и у вас есть GNU sed, то:
sed '/^pattern/ {$!N; /\n[0-9]/b; s/$/\n1000/M}' file
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000
Как это работает:
- если текущая строка начинается с
pattern
то- если мы не достигли EOF, добавьте следующую строку
- если после символа новой строки стоит цифра (это можно сделать более конкретно), то
b
переходим на следующую строку; в противном случае - замените первую строку, заканчивающуюся новой строкой и
1000
Модификатор , специфичный для GNU, M
позволяет $
сопоставлять либо \n
либо , $
так что он обрабатывает как «нормальный» случай, так и случай EOF, когда последующая строка не добавляется.
решение4
awkрешение:
awk '{ if ($0 ~ /pattern/) { # if it's a `pattern` line
if ((getline nl) > 0) { # check if next record exists
# if next record hasn't number - insert `1000`, otherwise - print current and next records as they are
print ((nl !~ /^[0-9]/)? $0 ORS 1000 ORS nl: $0 ORS nl)
} else {
print $0 ORS 1000 # if the file ends up with pattern - insert `1000`
}
} else {
print $0 # print other record
}
}' file
Выход:
pattern.d
17.91
17.55
pattern.b
1000
pattern.a
7.21
9.34
pattern.c
1000