Как я могу соединить две строки в файле, если они обе соответствуют шаблону?

Похоже, вы просто хотите заменить все, что идет после знака равенства, на "0.50". Это легко сделать с помощьюawk:

$ echo 'schedule="0.25"' | awk -F = 'BEGIN { OFS=FS } $1 == "schedule" { $2 = "\"0.50\"" } { print }'
schedule="0.50"

Программа awkспециально ищет запись, чье первое=-поле с разделителями равно schedule. Когда он найден, он заменяет второе поле на "0.50".

Если 0.50является переменной, вы можете передать это значение в скрипт awkследующим образом:

$ newval=0.222
$ echo 'schedule="0.25"' | awk -v nv="$newval" -F = 'BEGIN { OFS=FS } $1 == "schedule" { $2 = sprintf("\"%s\"", nv) } { print }'
schedule="0.222"

И, очевидно, если scheduleтакже может меняться,

$ newval=0.222
$ variable=schedule
$ echo 'schedule="0.25"' | awk -v v="$variable" -v nv="$newval" -F = 'BEGIN { OFS=FS } $1 == v { $2 = sprintf("\"%s\"", nv) } { print }'
schedule="0.222"

С помощью sedвы можете просто проигнорировать все, что идет после =, и заменить его чем угодно:

$ echo 'schedule="0.25"' | sed 's/=.*/="0.50"/'
schedule="0.50"

Чтобы убедиться, что мы заменяем только значение для schedule, а не значение какого-либо другого параметра,

$ echo 'schedule="0.25"' | sed '/^schedule=/s/=.*/="0.50"/'
schedule="0.50"

Это ставит условие нашей замены; Строка должна иметь строку schedule=в начале, чтобы она сработала.

Мы могли бы даже вставить переменные оболочки в наше sedвыражение, но имейте в виду, что мы должны убедиться, что значения этих переменных не нарушают синтаксис sed(, поскольку содержат символы, влияющие на сопоставление или разграничение команд):

$ newval=0.222
$ variable=schedule
$ echo 'schedule="0.25"' | sed "/^$variable=/s/=.*/=\"$newval\"/"
schedule="0.222"

В отличие от примера awk, здесь мы полагаемся на оболочку для ввода значений наших переменных в sedсценарий редактирования. Обычно это классифицируется как уязвимость внедрения кода в тех случаях, когда значения переменных не находятся под нашим контролем (, например, когда мы считываем их из предоставленного пользователем источника ).

2
01.11.2021, 17:54
2 ответа

Usin sedс нулевым символом в качестве разделителя(-z):

$ sed -z 's/\([A-Z][a-z]\+\)\n\([A-Z][a-z]\+\)/\1 \2/'
Hello
i
am
John Smith
2
01.11.2021, 20:12

Использование Raku (, ранее известного как Perl _6)

raku -e 'given lines.join("\n") { S/ $<first>=[<upper><lower>+] \n $<last>=[<upper><lower>+] /$<first> $<last>/.put};'

Пример ввода:

Hello
i
am
John
Smith
goodbye

Пример вывода:

Hello
i
am
John Smith
goodbye

Выше приведено решение, закодированное на Raku, члене семейства языков Perl -. Код подчеркивает несколько преимуществ использования Raku. Вкратце, rakuвызывается в командной строке с флагом -e, который указывает Raku выполнить следующий -лайнер-код (, а не, например, интерпретировать следующее как сценарий -. файл для открытия/исполнения ).

Данные передаются givenРаку в форме lines, но по мере того, как подпрограмма Раку linesauto -жует ввод, данныеjoin-переводятся с новыми строками. Хотя это может показаться немного запутанным, на самом деле это экономит шаг в конце. Но что более важно, подпрограмма Раку linesлениво считывает данные, а это означает, что приведенный выше код должен эффективно использовать память -.

Раку реализует S///"не -деструктивный" оператор, который подобен (, если не идентичен )знакомому s///оператору (Раку тоже имеет такой ). Оператор Capital-Sимеет одно преимущество, заключающееся в том, что он «оставляет исходную строку нетронутой и возвращает результирующую строку вместо $/ (переменной соответствия )».

При сопоставлении (левой )половины оператора S///используютсяименованные захваты . Механизм регулярных выражений сначала ищет [<upper><lower>+]и присваивает его именованному захвату $<first>, затем ищет\n(новую строку )и, наконец, ищет другой [<upper><lower>+], на этот раз присваивая его именованному захвату. $<last>. Наконец, в замене (правой )половины оператора S///два именованных захвата $<first> $<last>используются для замены левого -совпадения, хотя на a пробел и без новой строки \nмежду ними.

Вот и все. Примечание,приведенный выше код будет свернут только что-то вроде George\nHerbert\nWalker\nBushиз 4 строк в 3(George Herbert\nWalker\nBush).

[Если вы хотите, чтобы все последовательные вхождения [<upper><lower>+]возвращались в одной строке, пожалуйста, не стесняйтесь публиковать этот вопрос].

https://docs.raku.org/language/regexes#S///_non-destructive_substitution
https://docs.raku.org/language/regexes#index-entry-regex__Named_captures-Named_captures
https://raku.org

0
09.11.2021, 21:31

Теги

Похожие вопросы