как поместить все теги каталога в разные переменные

как поместить все теги каталога в разные переменные

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

Ниже приведено то, что я нашел:

<Directory />
    AllowOverride none
    Order deny, allow
    Deny from all
</Directory>
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>

Необходимый:

# echo $var1
<Directory /> 
AllowOverride none 
Order deny, allow 
Deny from all 
</Directory>

# echo $var2
<Directory "/var/www"> 
AllowOverride None  
Require all granted 
</Directory>

Обратите внимание: существует не просто 2 тега каталога, а множество тегов каталога без какого-либо пробела между ними. Каждый отдельный каталог должен храниться в отдельной переменной.

Заранее благодарю

решение1

Вы можете перебирать строки файла и добавлять новые строки в строку, пока не встретите тег </Directory>.

Если у вас есть только Directoryтеги, код будет намного проще. Вам нужно будет объявлять varXпеременные по мере использования, declareесли вы не знаете, сколько у вас тегов.

STR=""
i=1
DIRTAG=false
while read -r LINE; do
    if grep -q '^<Directory' <<< $LINE; then
        DIRTAG=true
    fi
    if $DIRTAG; then
        STR+="$LINE
"
    fi
    if grep -q '^</Directory>' <<< $LINE; then 
        declare var$i="\"\"\"$STR\"\"\"" #You're not clear on the quotes
        STR=""   
        i=$((i+1))
        DIRTAG=false
    fi
done < t.txt

Теперь echo "$var1"; echo "$var2"выводится следующее (не забудьте двойные кавычки. В противном случае в распечатанном выводе переносы строк будут пробелами)

"""<Directory />
AllowOverride none
Order deny, allow
Deny from all
</Directory>
"""
"""<Directory "/var/www">
AllowOverride None
Require all granted
</Directory>
"""

Если вы не знаете количество тегов, вы можете использовать это для перебора созданных переменных.

for j in `seq 1 $((i-1))`; do
    var=var$j
    echo "${!var}"
done

решение2

Вы можете обработать файл, чтобы преобразовать его в список определений переменных, а затем получить его источник. Например, вы можете добавить пустую строку после каждого закрывающего </Directory>тега, а затем использовать режим абзаца perl, чтобы прочитать каждую запись как одну строку:

$ sed 's|</Directory>|</Directory>\n|' file | 
    perl -000 -lne 'print "var" . ++$k . "=\"$_\"";' 
var1="<Directory />
    AllowOverride none
    Order deny, allow
    Deny from all
</Directory>"

var2="<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>"

И вы можете напрямую использовать его для установки переменных в вашей текущей оболочке:

$ . <(sed 's|</Directory>|</Directory>\n|' file | 
    perl -000 -lne 'print "var" . ++$k . "=\"$_\"";' file )

$ echo "$var1"
<Directory />
    AllowOverride none
    Order deny, allow
    Deny from all
</Directory>

$ echo "$var2"
<Directory /var/www>
    AllowOverride None
    Require all granted
</Directory>

Объяснение

  • sed s|</Directory>|</Directory>\n|' file: добавьте новую строку после каждого закрывающего </Directory>тега.
  • -000: это включает "режим абзаца" perl, где "строка" определяется двумя последовательными символами новой строки, по сути, пустой строкой. Таким образом, вместо настоящих строк каждая "строка" теперь является абзацем. Это позволяет нам рассматривать все между открытием и закрытием < Directory />как одну строку, поскольку каждая запись отделена пустой строкой.
  • -lne: -lудаляет конечные символы новой строки и добавляет \nк каждому print. -nсчитывает входной файл построчно (см. выше, что означает «строка» в этом контексте) и применяет скрипт, заданный , -eк каждой строке.
  • print "var" . ++$k . "=\"$_\"": вывести желаемый формат вывода: строку var, за которой следует число, увеличивающееся для каждой обработанной строки ( ++$k), затем =\"( "необходимо экранировать, так \"как мы находимся внутри строки в двойных кавычках) и текущую «строку» ( $_), за которой следует закрывающий ".
  • . <(perl ...): .это исходная команда, она прочитает файл, который вы ей дадите, и запустит его содержимое в текущем сеансе. Это <()называетсязамена процесса, по сути, это позволяет нам обрабатывать вывод команды так, как будто это файл. Обратите внимание, что не все оболочки поддерживают это, поэтому если ваша не поддерживает, вам, возможно, придется сохранить вывод в файл, а затем указать этот файл.

Связанный контент