2015-04-07 3 views
0

У меня есть несколько систем 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 

Очевидно, что я хочу, чтобы сценарий выполнял мою работу. У меня есть стандартный ш, Ksh, AWK, SED, Grep, Perl, сократить и т.д. Так как это 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 это будет некоторый тип фрагмента кода на основе оболочки, который я могу добавить к моему сценарию изменения , Я открыт для других вариантов, особенно если решение проще.

ответ

0

Непроверено Баш и др

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

OP сказал: «Поскольку это AIX, у меня нет доступа к версиям GNU этих утилит». – ThisSuitIsBlackNot

+0

Справа. Спасибо что подметил это. –

+0

Я могу иногда работать с GNU, например, «sed -i». человек (1) все еще мой друг на том, что работает, а что нет. – IAmJeff

0

Этот код Perl будет делать, спросите вы. Он ожидает, что путь к файлу будет изменен как параметр в командной строке.

Обратите внимание, что он считывает весь входной файл в массив @config, а затем перезаписывает тот же файл с измененными данными.

Он работает, создавая хэш %values из комбинации элементов, уже присутствующих в строке foo =, и список элементов по умолчанию в @defaults.Комбинация отсортированы в алфавитном порядке и присоединился к eith запятой

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 
+0

Вам нужно добавить строку 'foo', если она не найдена в файле. –

+0

Или, по крайней мере, определить, нет ли 'foo'. Вероятно, мне придется использовать другие вещи, не упомянутые в вопросе_, чтобы вставить его в нужное место. – IAmJeff

0

Некоторые грязный удар/СЭД:

#!/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 
+0

Возможно, у меня есть BASH. Похоже, что это будет работать с KORN. Если бы я мог бы поддержать вас за 'lineno = $ (cut -d: -f1 <<<" $ {v} 0: ")', я бы это сделал. Я не знал, что ты можешь это сделать с этими. – IAmJeff

+0

Кроме того, все это использование tr для сортировки/uniq строки ** очень круто **! – IAmJeff

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 
Смежные вопросы