LINUX.ORG.RU

Сортировка строк внутри секций конфигурационного файла.

 ,


0

1

Здравствуйте.

Есть файл такого формата:

/section1
set parameter1
add parameter 2
set parameter 3
/section2
add parameter1
/section3
set parameter1
…

и тд, сочетания строк внутри section могут быть самые разные. Я хочу получить отсортированные по алфавиту в прямом порядке параметры внутри каждой секции:

/section1
add parameter 2
set parameter1
set parameter 3
/section2
add parameter1
/section3
set parameter1
…

Порядок секций меняться не должен.

Пока мне пришло в голову громоздкое решение: читать построчно, если в текущей строке содержится '/', то писать в файл результата, затем читать все строки, до встретившегося нового '/' в отдельный файл, на него применять sort, переносить отсортированное содержимое временного файла в результат и переходить к началу алгоритма.

Есть ли более быстрые и простые способы получить то, что надо? ЯП: bash/awk


Я хочу получить отсортированные по алфавиту в прямом порядке параметры внутри каждой секции:

зачем?

Есть ли более быстрые и простые способы получить то, что надо? ЯП: bash/awk

в bash есть массивы. Вместо сортировки можно использовать ассоциативный массив (годно для конфигов).

drBatty ★★
()
if [ "`head -c 1 input_file`" != '/' ]; then
  echo Error: wrong file format'' 1>&2
  exit 1
fi

i=0
while read sections[$i] && read -r -d / lines[$i]; do
  ((i++))
done < <(tail -c +2 input_file; echo /)

echo -n > output_file
for i in `seq 0 $((${#sections[*]} - 2))`; do
  (echo "/${sections[$i]}"; echo "${lines[$i]}" | sort) >> output_file
done
LinuxUser ★★★
()
Последнее исправление: LinuxUser (всего исправлений: 1)

как-то так:

sort.awk

/^\// {
    n=asort(l)
    for (i = 1; i <= n; i++) {
        print l[i]
        delete l[i]
    }
    i = 0
}

{
    l[i] = $0
    i++
}

ENDFILE {
    n=asort(l)
    for (i = 1; i <= n; i++)
      print l[i]
}

awk -f sort.awk config_file

ananas ★★★★★
()
Ответ на: комментарий от HolyBoy

Настраиваемое оборудование чувствительно к порядку применения опций.

два варианта уже сказали, вот третий:

  • нумеруем секции вот так:
    $ echo "/section1
    set parameter1
    add parameter 2
    set parameter 3
    /section2
    add parameter1
    /section3
    set parameter1
    " | sed -r '1{x;s/.*/0/;x};\~^/section~{h;s///;x};G;s/(.*)\n(.*)/\2\t\1/;'
    1	/section1
    1	set parameter1
    1	add parameter 2
    1	set parameter 3
    2	/section2
    2	add parameter1
    3	/section3
    3	set parameter1
    3	
    
  • сортируем. При этом, т.к. секции пронумерованы, местами они не меняются.
  • убираем ненужные номера секций. sed -r 's/\S+\s+//'
drBatty ★★
()
Ответ на: комментарий от drBatty
$ echo "/section1
set parameter1
add parameter 2
set parameter 3
/section2
add parameter1
/section3
set parameter1
" | sed -r '1{x;s/.*/0/;x};\~^/section~{h;s///;x};G;s/(.*)\n(.*)/\2\t\1/'|sort|sed -r 's/\S+\s+//'
/section1
add parameter 2
set parameter 3
set parameter1
/section2
add parameter1

/section3
set parameter1
drBatty ★★
()
Ответ на: комментарий от LinuxUser

Спасибо за помощь!

Твой скрипт был не совсем тем, что требовалось, т.к. вид обрабатываемого файла не постоянный, количество параметров в секции может меняться. Показанный пример — это только одно из возможных состояний.

Однако, посмотрев приведённые варианты, я родил вот такое:

#!/bin/bash

F="$1"
RES="$2"

i=0
unset vals
while read line; do
    if [ "$(expr "$line" : '\(\/\)')" == "/" ]; then
        (for j in $(seq 0 $((${#vals[*]} - 1))); do
            echo "${vals[$j]}"
        done) | sort
        unset vals
        echo "$line"
        i=0
    else
        vals[$i]="$line"
        ((i++))
    fi
done < "$F"

(for j in $(seq 0 $((${#vals[*]} - 1))); do
    echo "${vals[$j]}"
done) | sort

Этот вариант уже делает то, что надо. Он, конечно, не особо чистый, надо, например, повторяющийся код вынести в функцию, но это уже мелочи.

HolyBoy
() автор топика
Последнее исправление: HolyBoy (всего исправлений: 1)

Спасибо всем за помощь.

Проблема решена.

HolyBoy
() автор топика
Ответ на: комментарий от HolyBoy

количество параметров в секции может меняться

Да пожалста:

neo@nvh:/tmp$ cat input_file
/section1
set parameter1
add parameter 2
set parameter 3
foo
bar
/section2
bla
add parameter1
blu
/section3
test
set parameter1
neo@nvh:/tmp$ ./script
neo@nvh:/tmp$ cat output_file
/section1
add parameter 2
bar
foo
set parameter1
set parameter 3
/section2
add parameter1
bla
blu
/section3
set parameter1
test
neo@nvh:/tmp$

LinuxUser ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.