Я извлек все теги каталогов из файла. Теперь я застрял в ситуации, когда мне нужно сохранить все теги каталогов в разных переменных, как показано ниже. Заранее благодарен.
Ниже приведено то, что я нашел:
<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 ...)
:.
это исходная команда, она прочитает файл, который вы ей дадите, и запустит его содержимое в текущем сеансе. Это<()
называетсязамена процесса, по сути, это позволяет нам обрабатывать вывод команды так, как будто это файл. Обратите внимание, что не все оболочки поддерживают это, поэтому если ваша не поддерживает, вам, возможно, придется сохранить вывод в файл, а затем указать этот файл.