Используется sed
например:
$ echo 'version: 1.8.0.110' | sed 's/\./-/3'
version: 1.8.0-110
Пояснение:
sed s/search/replace/x
ищет строку и заменяет вторую. x
определяет, какое вхождение заменить -здесь 3-м. Часто g
используется вместо x
для обозначения всех вхождений.
Здесь мы хотим заменить точку .
, но это специальный символ регулярного выражения sed
, ожидаемый в термине search
. Поэтому мы используем обратную косую черту от .
до \.
, чтобы указать литерал .
.
Поскольку мы используем здесь специальные символы в аргументе sed
(, обратную косую черту\
)нам нужно поместить весь аргумент в одинарные кавычки ''
. Многие люди всегда используют здесь кавычки, чтобы не столкнуться с проблемами при использовании символов, которые могут быть специфическими для оболочки (, например пробел).
Если у вас есть только одно вхождение последовательности BBBB*
,вы можете указать sed
удалить только первый BBBB
, которому предшествует другой символ.
sed 's/^ABCD.*[^B]BBBB//'
Если последовательность BBBB
начинается только один раз в каждой строке, это должно сработать.
Обратите внимание, что это не будет работать со строками типа:
ABCDEBBBBBFBBBBBXYZ
, потому что это два вхождения BBBB
, которым предшествует не -B, и жадный алгоритм также поймает второе.
Сделать то, что вы просили для(remove everything starting with the ABCD up to, and including, the first occurence of 4 consecutive Bs.
)с любым awk, было бы:
$ awk -v beg='ABCD' -v end='BBBB' '
{ gsub(end,"\n") }
match($0,beg"[^\n]+\n") { $0=substr($0,1,RSTART-1) substr($0,RSTART+RLENGTH) }
{ gsub(/\n/,end) }
1' file
BBBBBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBBBXYZ
Это работает независимо от того, стоит ли буква ABCD первой в строке или перед ней может стоять BBBB и т. д.:
$ echo 'xyz BBBB foo ABCD bar BBBB etc BBBB anon' |
awk -v beg='ABCD' -v end='BBBB' '{gsub(end,"\n")} match($0,beg"[^\n]+\n"){$0=substr($0,1,RSTART-1) substr($0,RSTART+RLENGTH)} {gsub(/\n/,end)} 1'
xyz BBBB foo etc BBBB anon
Задачу можно разбить на два этапа. Ставим отметку и потом удаляем:
sed '/ABC/s/B\{4\}/&\n/;s/ABC.*\n//' file
\n
-отметка
Чтобы избежать ложных случаев, когда шаблон BBBB
стоит перед шаблоном ABC
, можно добавить еще одну команду, которая снимет ложную отметку:
sed 's/B\{4\}/&\n/;s/ABC.*\n//;s/\n//' file
Использование Raku (, ранее известного как Perl _6)
raku -pe 's/^^ ABCD.*? B**4 //;'
Пример ввода:
ABCDABCBCBBBCBCDDBBBBBBBBBBBBBBBBBBBBBBBBBXYZ
ABCDCCCBCCBBBBBBBBBBBBBBBBBBBBBBXYZ
ABCDACDCDCCCCBBBBBBBBBBBBBBBBBBBBBBBBXYZ
Пример вывода:
BBBBBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBBBXYZ
Выше приведено решение, написанное на Raku, члене семейства языков программирования Perl -. Raku включает сложное обновление хорошо зарекомендовавшего себя -механизма PCRE. Тем не менее, в приведенном выше коде используется знакомый оператор s///
в сочетании с флагами-pe
(auto -построчной печати ).
Для описанной проблемы решение так же просто, как преобразование «жадного» .*
регулярного выражения в «бережливое» .*?
регулярное выражение. Простого включения ?
достаточно, чтобы Раку знал, что нужно остановиться в соответствующем месте, ближайшем к левому-концу последовательного-B
прогона (регулярное выражение B**4
говорит Раку искать 4 -последовательных B
с ).
Это самое простое решение. Однако, если вам нужна помощь в визуализации того, что удаляется, просто переключитесь на -ne
не -построчный флаг автопечати (s )в сочетании сS///
(недеструктивной подстановкой -)илиm/…/
(соответствуют операторам ):
$ raku -pe 's/^^ ABCD.*? B**4 //;' file
BBBBBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBBBXYZ
$ raku -ne 'put S/^^ ABCD.*? B**4 //;' file
BBBBBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBXYZ
BBBBBBBBBBBBBBBBBBBBXYZ
$ raku -ne 'put s/^^ ABCD.*? B**4 //;' file
ABCDABCBCBBBCBCDDBBBB
ABCDCCCBCCBBBB
ABCDACDCDCCCCBBBB
$ raku -ne 'm/^^ ABCD.*? B**4 /.put;' file
ABCDABCBCBBBCBCDDBBBB
ABCDCCCBCCBBBB
ABCDACDCDCCCCBBBB