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