我有几个带有配置文件的AIX系统,我们称之为 / etc / bar / config 。该文件可能有也可能没有为 foo 声明值的行。一个例子是:
foo = A_1,GROUP_1,USER_1,USER_2,USER_3
foo 行在所有系统上可能相同也可能不同。不同的系统可以具有不同的值并且可以具有不同数量的值。我的任务是添加"最低限度"所有系统上 config 文件中的值。最低限度的行看起来像这样。
foo = A_1,USER_1,SYS_1,SYS_2
如果该行不存在,我必须创建它。如果该行确实存在,我必须合并这两行。使用我的例子,结果就是这样。值的顺序无关紧要。
foo = A_1,GROUP_1,USER_1,USER_3,USER_2,SYS_1,SYS_2
显然我想要一个脚本来完成我的工作。我有标准 sh , ksh , awk , sed , grep ,< em> perl , cut 等。由于这是AIX,我无法访问这些实用程序的GNU版本。
最初,我有一个带有这些命令的脚本来替换整个 foo 行。
cp /etc/bar/config /etc/bar/config.$$
sed "s/foo = .*/foo = A_1,USER_1,SYS_1,SYS_2/" /etc/bar/config.$$ > /etc/bar/config
但这只是取代了这条线。它确实考虑了任何预先存在的配置,包括缺少的一行。我在脚本中进行其他配置修改,例如向其他文件添加完全唯一的行并重新启动进程,因此我 perfer 这是基于shell的某种类型我可以添加到我的更改脚本的代码段。我对其他选项持开放态度,特别是如果解决方案更简单的话。
答案 0 :(得分:0)
未经测试的bash等。
config=/etc/bar/config
default=A_1,USER_1,SYS_1,SYS_2
pattern='^foo[[:blank:]]*=[[:blank:]]*' # shared with grep and sed
if current=$( grep "$pattern" "$config" | sed "s/$pattern//" )
then
new=$( echo "$current,$default" | tr ',' '\n' | sort | uniq | paste -sd, )
sed "s/$pattern.*/foo = $new/" "$config" > "$config.$$.tmp" &&
mv "$config.$$.tmp" "$config"
else
echo "foo = $default" >> "$config"
fi
香草perl解决方案:
perl -i -lpe '
BEGIN {%foo = map {$_ => 1} qw/A_1 USER_1 SYS_1 SYS_2/}
if (s/^foo\s*=\s*//) {
$found=1;
$foo{$_}=1 for split /,/;
$_ = "foo = " . join(",", keys %foo);
}
END {print "foo = " . join(",", keys %foo) unless $found}
' /etc/bar/config
答案 1 :(得分:0)
此Perl代码将按您的要求执行。它期望将文件的路径修改为命令行上的参数。
请注意,它会将整个输入文件读入数组@config
,然后使用修改后的数据覆盖同一文件。
它的工作原理是根据%values
行中已存在的项目和foo =
中默认项目列表的组合构建哈希@defaults
。组合按字母顺序排序,并以逗号
use strict;
use warnings;
my @defaults = qw/ A_1 USER_1 SYS_1 SYS_2 /;
my ($file) = @ARGV;
my @config = <>;
open my $out_fh, '>', $file or die $!;
select $out_fh;
for ( @config ) {
if ( my ($pfx, $vals) = /^(foo \s* = \s* ) (.+) /x ) {
my %values;
++$values{$_} for $vals =~ /[^,\s]+/g;
++$values{$_} for @defaults;
print $pfx, join(',', sort keys %values), "\n";
}
else {
print;
}
}
close $out_fh;
<强>输出强>
foo = A_1,GROUP_1,SYS_1,SYS_2,USER_1,USER_2,USER_3
答案 2 :(得分:0)
一些脏bash / sed:
#!/usr/bin/bash
input_file="some_filename"
v=$(grep -n '^foo *=' "$input_file")
lineno=$(cut -d: -f1 <<< "${v}0:")
base="A_1,USER_1,SYS_1,SYS_2,"
if [[ "$lineno" == 0 ]]; then
echo "foo = A_1,USER_1,SYS_1,SYS_2" >> "$input_file"
else
all=$(sed -n ${lineno}'s/^foo *= */'"$base"'/p' "$input_file" | \
tr ',' '\n' | sort | uniq | tr '\n' ',' | \
sed -e 's/^/foo = /' -e 's/, *$//' -e 's/ */ /g' <<< "$all")
sed -i "${lineno}"'s/.*/'"$all"'/' "$input_file"
fi
答案 3 :(得分:0)
由于您没有提供样本输入和预期输出,我无法对此进行测试,但这是正确的方法:
awk '
/foo = / { old = ","$3; next }
{ print }
END {
split("A_1,USER_1,SYS_1,SYS_2"old,all,/,/)
for (i in all)
if (!seen[all[i]]++)
new = (new ? new "," : "") all[i]
print "foo =", new
}
' /etc/bar/config > tmp && mv tmp /etc/bar/config