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

Короткий ответ: синтаксис, который вы используете для сортировки, взят из старой версии POSIX. Из руководства coreutils для sort:

On systems not conforming to POSIX 1003.1-2001, sort supports a traditional origin-zero syntax ‘+pos1 [-pos2]’ for specifying sort keys. The traditional command ‘sort +a.x -b.y’ is equivalent to ‘sort -k a+1.x+1,b’ if y is ‘0’ or absent, otherwise it is equivalent to ‘sort -k a+1.x+1,b+1.y’.

This traditional behavior can be controlled with the _POSIX2_VERSION environment variable (see Standards conformance); it can also be enabled when POSIXLY_CORRECT is not set by using the traditional syntax with ‘-pos2’ present.

Scripts intended for use on standard hosts should avoid traditional syntax and should use -k instead.

Хотя можно восстановить традиционное поведение, проще использовать новый синтаксис.

Опция +1определяет ключ сортировки от второго поля до конца строки. Эквивалентная новая опция -k 2. Таким образом, новые команды sort, которые вы должны использовать, соответственно:

sort -k 2 -t: ~/source/corp_phones
sort -k 7 -t: ~/source/corp_phones
sort -k 5 -t: ~/source/corp_phones

0
07.04.2020, 13:48
2 ответа

Вы можете перебирать строки файла и добавлять новые строки в строку, пока не встретите тег </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
1
28.04.2021, 23:18

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

Теги

Похожие вопросы