Я пытаюсь понять эту строку из скрипта оболочки. Я знаю, что это $(..)
означает запустить ..
и вставить его вывод туда, где вы найдете $()
в операторе. Но что происходит между этими скобками? Что делает \ls
и как это связано с \
в предыдущих строках? Это \\
разделение на две строки? Это \ls
то же самое, что и обычное ls
?
APPCLASSPATH=$CLASSPATH:$({ \
\ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \
\ls -1 "$VOLTDB_LIB"/*.jar; \
\ls -1 "$VOLTDB_LIB"/extension/*.jar; \
} 2> /dev/null | paste -sd ':' - )
решение1
Вывод трех ls
команд передается команде paste
, которая объединяет их в значение:
$VOLTDB_VOLTDB"/voltdb-*.jar:$VOLTDB_LIB"/*.jar:$VOLTDB_LIB"/extension/*.jar
ПРИМЕЧАНИЕ:Переменные $VOLTDB_VOLTDB
и $VOLTDB_LIB
будут расширены, и для каждой из этих команд может быть больше значений, чем просто один файл ls
. Видите *
там? Это символ glob, который действует как подстановочный знак и расширяется до чего угодно между левой стороной (voltdb-) и правой стороной (.jar), например.
Они будут соответствовать:
voltdb-1.jar
voltdb-blah.jar
voltdb-12345.jar
Затем все включается в переменную APPCLASSPATH
:
APPCLASSPATH=$CLASSPATH:$VOLTDB_VOLTDB"/voltdb....etc.
Команда вставки
Вот пример, в котором я использую seq
команду для генерации последовательности чисел от 1 до 10.
$ seq 10 | paste -sd ':' -
1:2:3:4:5:6:7:8:9:10
Вы можете видеть, что paste
команда объединяет выходные данные и разделяет их двоеточием ( :
).
Вы также можете повторить команду примера следующим образом:
$ { echo "hi1"; echo "hi2"; echo "hi3"; } | paste -sd ':' -
hi1:hi2:hi3
ПРИМЕЧАНИЕ:Команда -
вставки указывает, что необходимо взять входные данные из STDIN и вывести каждый аргумент по мере их поступления, разделив его точкой :
.
Используя различные переключатели, paste
можно также разбить данные на группы в зависимости от количества -
символов «'» после них.
Вставить примеры
Вот пример с 2 -
-мя.
$ seq 10 | paste - -
1 2
3 4
5 6
7 8
9 10
Вот 3 -
.
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
Итак, он сообщает paste
, сколько аргументов paste
должно быть напечатано в каждой строке. Но не путайтесь, пример, с которым вы имеете дело, просто берет входные данные из STDIN, разделяет каждый аргумент пробелами и печатает его с последующим :
. При указании нескольких -
' вы указываете paste
брать аргументы, 2 и по одному, 3 за раз и т. д.
Аргументы по 2 за раз, разделенные :
точкой:
$ seq 10 | paste -d ':' - -
1:2
3:4
5:6
7:8
9:10
$ seq 10 | paste -d ':' - - -
1:2:3
4:5:6
7:8:9
10::
Кстати, если вы включаете переключатель, -s
вы говорите, paste
что нужно принимать аргументы последовательно (серийно). Посмотрите, что происходит, когда вы используете его в одном из примеров выше.
2 за раз:
$ seq 10 | paste -sd ':' - -
1:2:3:4:5:6:7:8:9:10
3 за раз:
$ seq 10 | paste -sd ':' - - -
1:2:3:4:5:6:7:8:9:10
решение2
$(command)
выполняет команду и подставляет ее вывод.
{ list; }
— это групповая команда, выполняющая несколько команд в текущей среде оболочки. Она похожа на (list)
, но не создает подоболочку.
\command
используется для игнорирования псевдонимов команд, которые могут существенно изменить ожидаемое поведение команд.
В \
конце строки просто означает, что эта строка продолжается, поэтому оболочка будет видеть следующую строку как часть текущей. Обычно не требуется, когда это очевидно из контекста (открывающая скобка или кавычка).
решение3
APPCLASSPATH=$CLASSPATH:$({ \ \ls -1 "$VOLTDB_VOLTDB"/voltdb-*.jar; \ \ls -1 "$VOLTDB_LIB"/*.jar; \ \ls -1 "$VOLTDB_LIB"/extension/*.jar; \ } 2> /dev/null | paste -sd ':' - )
\ls
похож на ls
, за исключением того, что если ls
это псевдоним, обратная косая черта предотвращает расширение псевдонима. Это гарантирует, что ls
используется команда, а не какой-либо псевдоним, который может добавить нежелательный вывод, такой как суффикс классификатора ( -F
).
Команды ls
, вызываемые с существующими именами файлов в качестве аргументов, перечисляют свои аргументы, по одному на строку. Параметр -1
не имеет эффекта, поскольку вывод ls
отправляется в канал, а не на терминал. Если ls
получает аргумент, который не является именем существующего файла, он ничего не отображает в своем стандартном выводе и вместо этого отображает ошибку. Ошибки от ls
команд перенаправляются в никуда с помощью 2> /dev/null
. Есть две причины, по которым ls
может получить аргумент, который не является файлом: если одна из переменных не ссылается на существующий читаемый каталог или если нет файла, соответствующего шаблону подстановочных знаков. В любом случае шаблон передается неразвернутым в ls
.
Обратные косые черты в конце строк заставляют оболочку игнорировать следующую новую строку. Ни одна из них здесь не полезна, поскольку в каждой точке, где они используются, оболочка ожидает необязательную новую строку.
Скобки { … } группируют команды. Составная команда { \ls …; \ls …; \ls … ; }
передается по конвейеру paste
и ее ошибки перенаправляются в /dev/null
.
Команда paste
объединяет все входные строки с a :
между ними. Это эквивалентно , за tr '\n' :
исключением того, что a не ставится :
в конце.
Подстановка команды приводит к интерполяции $(…)
выходных данных в , после значения переменной с двоеточием для разделения двух частей.paste
APPCLASSPATH
CLASSPATH
Вот упрощенная версия. Она немного отличается от оригинала тем, что если ни один из шаблонов подстановочных знаков не соответствует ничему, то APPCLASSPATH
будет равно CLASSPATH
без дополнительного двоеточия в конце (что, вероятно, желательно).
APPCLASSPATH=$CLASSPATH:$(
\ls "$VOLTDB_VOLTDB"/voltdb-*.jar "$VOLTDB_LIB"/*.jar "$VOLTDB_LIB"/extension/*.jar |
tr '\n' :) 2>/dev/null
APPCLASSPATH=${APPCLASSPATH%:}