Хотя теоретически возможно написать регулярное выражение, которое соответствует самой короткой строке, не соответствующей «false», это сложно. Различные другие языки имеют синтаксис для выбора кратчайшего пути, но awk не входит в их число.
Таким образом, есть 3 подхода, которые можно использовать, предполагая, что вы не хотите писать сложное выражение.
Для подхода № 3.
#!/usr/bin/awk
/PATTERN.*false/ {
for(i=1;i<=NF;i++) {
if ($i ~ /PATTERN/) flag=1;
if ($i == "false" && flag==1) {
$i="true"
flag=0
}
}
}
{print}
Это приведет к сворачиванию пробелов во входных данных.
Это решение реализует подход к разделению строки в PATTERN
(split
), замене первой false
на вторую часть(sub
)и объединению частей(for
loop иprintf
). Команда next
пропускает дальнейшую обработку этой входной строки. Остальные строки печатаются без изменений.(1
— всегда верное условие с действием по умолчанию.)
awk '/PATTERN.*false/ {
n=split($0,parts,"PATTERN");
sub("false", "true", parts[2]);
for(i=1;i<n;i++) {
printf("%s%s", parts[i], "PATTERN");
}
printf("%s\n", parts[n]);
next }
1'
Из вопроса неясно, всегда ли значение, соответствующее PATTERN
, равно false
, поэтому оно может заменить неправильное false
.
Пример ввода
colorA is false colorB is false PATTERN is false colorC is false colorD is false
colorA is false colorB is false PATTERN is true colorC is false colorD is false
приводит к этому результату
colorA is false colorB is false PATTERN is true colorC is false colorD is false
colorA is false colorB is false PATTERN is true colorC is true colorD is false
Отредактируйте в соответствии с комментарием RudiC :Если to -будет -измененным значением после PATTERN либо "true", либо "false", то эта возможная проблема можно избежать, заменив инструкцию sub("false", "true", parts[2]);
наsub("false|true", "true", parts[2]);
awk '/PATTERN.*false/ {
n=split($0,parts,"PATTERN");
sub("false|true", "true", parts[2]);
for(i=1;i<n;i++) {
printf("%s%s", parts[i], "PATTERN");
}
printf("%s\n", parts[n]);
next }
1'
При том же входном образце это приводит к
colorA is false colorB is false PATTERN is true colorC is false colorD is false
colorA is false colorB is false PATTERN is true colorC is false colorD is false
С GNU awk для соответствия третьего аргумента ()и gensub():
$ awk 'match($0,/(.*PATTERN)(.*)/,a){$0=a[1] gensub(/false/,"true",1,a[2])} 1' file
...
colorA is false colorB is false PATTERN is true colorC is false colorD is false
...
и с любым awk:
$ awk 'match($0,/.*PATTERN/){tail=substr($0,RSTART+RLENGTH); sub(/false/,"true",tail); $0=substr($0,1,RSTART+RLENGTH-1) tail } 1' file
...
colorA is false colorB is false PATTERN is true colorC is false colorD is false
...