使用 awk 从一个文件读取并将属性注入另一个文件



我有一个属性文件,其中包含数百行,如下所示mainfile.txt

del.frequencyMinutes = 360
del.gracePeriodMinutes = 4320
vol.operationsEnabled = true
vol.multiFolderContainer = false
pool.capacity.differential = 30
pool.cpu.differential = 30
vol.single.pool.maxVolSize = 100
vol.multi.pool.maxVoluSize = 20

我想要一个小文件,我想根据一些不同的测试设置保留一些更改,如下所示change.txt

del.frequencyMinutes = 1440
del.gracePeriodMinutes = 2000

change.txt中的属性(字段$1)与主文件中的属性匹配时,它们的值应覆盖到主文件中。 我尝试了以下代码,但缺少一些重要的东西:

awk -F= 'NR==FNR{val1=$1;val2=$2;next}{ if ($1==val1) printf $1" = "val2;else if ($1 != val1) print $0}' changes.txt mainfile.txt

我看到它只将change.txt中的第二个属性行注入mainfile.txt而缺少第一个属性行。所以

  1. 如何添加所有change.txt
  2. 上面的代码只打印结果,不写入主文件,那么我怎么能永久写入主文件呢?

我不太擅长 awk/shell 脚本,所以我感谢您解释我在这里做错了什么

我会按照以下方式使用 GNUAWK来完成此任务

awk 'BEGIN{FS=OFS=" = "}NR==FNR{arr[$1]=$2;next}($1 in arr){$2=arr[$1]}{print}' changes.txt mainfile.txt

这对changes.txt

del.frequencyMinutes = 1440
del.gracePeriodMinutes = 2000

mainfile.txt

del.frequencyMinutes = 360
del.gracePeriodMinutes = 4320
vol.operationsEnabled = true
vol.multiFolderContainer = false
pool.capacity.differential = 30
pool.cpu.differential = 30
vol.single.pool.maxVolSize = 100
vol.multi.pool.maxVoluSize = 20

给出输出

del.frequencyMinutes = 1440
del.gracePeriodMinutes = 2000
vol.operationsEnabled = true
vol.multiFolderContainer = false
pool.capacity.differential = 30
pool.cpu.differential = 30
vol.single.pool.maxVolSize = 100
vol.multi.pool.maxVoluSize = 20

说明:我将字段分隔符(FS)和输出字段分隔符(OFS)都设置为=,因此在更改一个字段行后仍然property = value,然后在处理第一个文件(NR==FNR)时,我将键属性的数组arr值设置为其值。 使用next,因此不执行其他操作。在除第一个文件外的所有文件中:如果属性(第一个字段,$1)是arr键之一,则将值(第二个字段,$2)设置为该键的值,始终print整行。

(在Gawk 4.2.1中测试)

当输入文件中有多个行时,您将覆盖以前的val1val2值。通常和非常常见的解决方案是将行读入关联数组。

awk -F= 'NR==FNR { a[$1] = $0; next }
$1 in a { print a[$1]; next } 1' changes.txt mainfile.txt >temp
mv temp mainfile.txt

当它看到该文件中的第一个字段时,这将打印来自changes.txt的输入,否则将打印原始输入行。结果将写入一个临时文件,然后我们重命名该文件以将其移回原始mainfile.txt之上。

这里的-F =是可疑的; 也许将其取出,和/或在检查它是否在a之前规范化$1周围的空格。Awk(或几乎所有通用编程语言)中的字符串比较认为,如果字符串在文本周围具有不同数量的空格,则字符串是不同的。

最后唯一的1是常见的 Awk 速记,意思是"如果你走到这一步,只需打印当前的输入行"。

最新更新