如何使用 awk 更改未知数值

如何使用 awk 更改未知数值

我是学习的新手awk
我有一个文件,其中包含以下行以及其他行:

TIMEOUT=200

我需要更改数值。
仅当我事先知道该值时,此命令才能更改该值:

awk '$0 == "TIMEOUT=200" { sub ("200","5") } { print }' file

如果我不知道该值,我应该使用什么命令?
像这样:

awk '$0 == "TIMEOUT=[0-9]" { sub ("[0-9]","5") } { print }' file

但是我尝试了该命令,它并没有改变任何东西。

答案1

  • 您的尝试不起作用,因为==仅测试完全相等。如果您的文件包含一行,确切地说是, TIMEOUT=[0-9]您的代码会识别它(并将其更改为TIMEOUT=[5-9])。但是,正如您所见,它与像这样的字符串不匹配TIMEOUT=42。您当然希望选择与模式匹配的行。一种方法是使用TIMEOUT=number~运算符代替==
    awk'$0~"超时=[0-9]" {行动声明}'
  • 了解如何使用~运算符,并知道您可以对单个字段进行测试。但是,有一种简写符号可以将整行与模式进行匹配:
    awk'/TIMEOUT=[0-9]/{行动声明}'
    当你能够使用它的时候,你也许会想使用它。
  • 所以现在如果我们这样做
    awk'/TIMEOUT=[0-9]/{sub(“[0-9]”,“5”)}{打印}'
    它将匹配TIMEOUT=200行 — 并将其更改为TIMEOUT=500,因为[0-9]仅匹配单个数字(数字),而不是多位数字。要查找(并替换)多位数字(一个或多个连续数字的字符串),请使用+字符(运算符),表示“前一个模式出现一次或多次”,如sub ("[0-9]+","5")
  • 但我在前面的列表中忽略了一个问题。虽然==测试完全的字符串, 并 测试包含与模式匹配的子字符串的字符串。例如, 将匹配如下行 ~ "pattern"/pattern//TIMEOUT=[0-9]/
    在美式足球中,暂停=30秒
    如果你觉得可以,那就好了。我猜你只想匹配一整行,所以你会想“锚定”模式,这样TIMEOUT必须位于行首,数字必须位于行尾。你可以使用^$字符来执行此操作,例如。/^TIMEOUT=[0-9]$/
    除了…
  •       …如前所述,[0-9]仅匹配一位数字,因此上面的内容将匹配TIMEOUT=7但不会匹配TIMEOUT=11。您需要。/^TIMEOUT=[0-9]+$/

总结

你需要做

awk ‘$0 ~ “^TIMEOUT=[0-9]+$” { sub (“[0-9]+”,“5”) } { 打印 }’  文件
或者

awk ‘/^TIMEOUT=[0-9]+$/ { sub (“[0-9]+”,“5”) } { 打印 }’  文件


我鼓励您学习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] (一位数字,先于零个或多个附加数字)。我更喜欢第二种形式,因为我认为它看起来更平衡,但它并不是很流行。

相关内容