- Ваша попытка не работает, потому что
==
проверяет только на точное равенство.
Если ваш файл содержит строку, в которой точно и буквально указано TIMEOUT=[0-9]
, ваш код распознает его (и изменит его на TIMEOUT=[5-9]
).
Но, как вы видели, он не совпадает со строками типа TIMEOUT=42
.
Вы, конечно, хотите выбрать линии, которые соответствуют шаблону TIMEOUT=number
.
Один из способов сделать это - использовать оператор ~
вместо ==
:
awk '$ 0 ~ "TIMEOUT = [0-9]" { оператор (ы) действия }'
- Хорошо понимать, как использовать оператор
~
, и знать, что вы можете выполнять тесты на отдельных полях.
Тем не менее, существует условное обозначение для сопоставления всей строки с шаблоном:
awk '/TIMEOUT = [0-9]/ { оператор (ы) действия }'
и вы можете использовать это, когда можете.
- Так что теперь, если мы сделаем
awk '/TIMEOUT = [0-9]/ {sub ("[0-9]", "5")} {print}'
он будет соответствовать строке TIMEOUT=200
- и изменится на TIMEOUT=500
, потому что [0-9]
соответствует только одной цифре (цифре), а не многозначной цифре.
Чтобы найти (и заменить) многозначное число (строку из одной или нескольких последовательных цифр), используйте символ +
(оператор), что означает "одно или несколько вхождений предыдущего шаблона", как в sub ("[0-9]+","5")
.
- Но я вкратце остановился на проблеме ранее в этом списке.
В то время как
==
проверяет точное равенство полной строки, ~ "pattern"
и /pattern/
test для строки, содержащей подстроку, которая соответствует шаблону.
Так, например, /TIMEOUT=[0-9]/
будет соответствовать строке, которая выглядит как
В американском футболе время ожидания = 30 секунд
Если с тобой все в порядке, хорошо.
Я предполагаю, что вы хотите сопоставить только целую строку, поэтому вам нужно "привязать" шаблон так, чтобы TIMEOUT
был в начале строки, а число - в конце.
Вы делаете это с символами ^
и $
, как в /^TIMEOUT=[0-9]$/
.
Кроме…
- … Как указано выше,
[0-9]
соответствует только одной цифре, так что выше будет соответствовать TIMEOUT=7
но не TIMEOUT=11
.
Вам нужно /^TIMEOUT=[0-9]+$/
.
TL; DR
Вам нужно сделать
awk '$0 ~ "^TIMEOUT=[0-9]+$" { sub ("[0-9]+","5") } { print }' file
или же
awk '/^TIMEOUT=[0-9]+$/ { sub ("[0-9]+","5") } { print }' file
Я призываю вас выучить awk
, так как он может быть очень полезным и очень мощным.
Однако, для такой простой задачи, как эта, вы можете обойтись более простым инструментом: sed
.
К сожалению, sed
обычно не поддерживает оператор +
(один или несколько).
В GNU sed
(версии, которая поставляется с Cygwin и большинством (если не всеми) дистрибутивами Linux), вы можете указать опцию -r
чтобы она распознала «расширенные регулярные выражения».
(Шаблоны типа [0-9]+
называются «регулярными выражениями».)
Так что вы могли бы сделать
sed -r '/^TIMEOUT=[0-9]+$/s/[0-9]+/5/'
Но некоторые (более старые) версии sed
не поддерживают опцию -r
и вообще не поддерживают расширенные регулярные выражения.
К счастью, вы можете обойти это: есть еще один специальный символ (оператор), *
, что означает « ноль или более вхождений предыдущего шаблона».
«Одна или несколько цифр» эквивалентны «одной цифре, за которой следуют ноль или более дополнительных цифр», поэтому мы можем перевести [0-9]+
в [0-9][0-9]*
и выполнить команду как
sed '/^TIMEOUT=[0-9][0-9]*$/s/[0-9][0-9]*/5/'
Вместо [0-9][0-9]*
вы также можете сделать [0-9]*[0-9]
(одна цифра, которой предшествует ноль или более дополнительных цифр).
Я предпочитаю вторую форму, потому что я думаю, что она выглядит более сбалансированной, но она не очень популярна.