#linux #bash
#linux #bash
Вопрос:
Я хотел бы встроить такую длинную команду в сценарий bash:
mycommand
--server myserver
--filename extremely/long/file/name/that/i/would/like/to/be/able/to/break/up/if/possible
--otherflag
--anotherflag
с разбитым длинным именем файла.
Я мог бы сделать это:
# Insufficiently pretty
mycommand
--server myserver
--filename extremely/long/file/name/
that/i/would/like/to/be/able/to/break/
up/if/possible
--otherflag
--anotherflag
но это нарушает поток. Я хотел бы иметь возможность написать это:
# Doesn't work
mycommand
--server myserver
--filename extremely/long/file/name/
that/i/would/like/to/be/able/to/break/
up/if/possible
--otherflag
--anotherflag
но это не работает, потому что это разбивает строковый литерал.
Есть ли способ сообщить bash, чтобы он разбил строковый литерал, но игнорировал любые начальные пробелы?
Ответ №1:
Это немного взломать, но это работает:
mycommand
--server myserver
--filename "extremely/long/file/name/"`
`"that/i/would/like/to/be/able/to/break/"`
`"up/if/possible"
--otherflag
--anotherflag
Bash объединяет смежные строковые литералы, поэтому мы используем это в своих интересах. Например, echo "hi" "there"
печатает hi there
, тогда echo "hi""there"
как печатает hithere
.
Он также использует оператор обратного отсчета и тот факт, что куча пробелов ни к чему не приводит.
Комментарии:
1. Вы можете поместить начало
`
в конец предыдущей строки вместо
продолжения строки… он сохраняет левый край чистым2. @Peter. O Я не понимаю, о чем вы говорите. Пожалуйста, уточните.
3. грязный хак для очистки вашего кода
4. Я даже не думаю, что вам нужно закрывать и снова открывать двойные кавычки. Это работает для меня:
"one` [line break] [whitespace] `two"
->"onetwo"
Ответ №2:
Вы можете использовать переменную :
file=extremely/long/file/name
file =/that/i/would/like/to/be/able/to/break
file =/up/if/possible
mycommand
--server myserver
--filename $file
--flag flag
Комментарии:
1. Хорошая идея. Вы можете сделать его более чистым, используя
=
оператор вместоfile=${file}/...
2. 1: на мой взгляд, это наименее запутанный подход. Цель ясна.
3. @Chriszuma Да, я забыл, что bash разрешил
=
оператор. Я отредактировал свой ответ.4. Найдите некоторое время для решения, но у всех есть небольшие проблемы, такие как добавление дополнительного пространства между. Спасибо
Ответ №3:
Можно также использовать переменную массива
file=(extremely/long/file/name
/that/i/would/like/to/be/able/to/break
/up/if/possible)
IFS=''
echo mycommand
--server myserver
--filename "${file[*]}"
--flag flag
Ответ №4:
В принципе, в bash для этого ничего не встроено.
Обычно с оболочкой больше проблем, чем она того стоит, но, тем не менее, вы можете попробовать псевдоним или функцию, например. j
j(){sed -e ':a;$!N;s/ *n *//g;ta' <<<"$1"}
echo "$(j "3 spaces
/hello
/world
/this
/is
/a
/long
/path
")"
# 3 spaces/hello/world/this/is/a/long/path
Ответ №5:
Я определяю короткую функцию strcat в верхней части моего скрипта bash и использую встроенный вызов, чтобы разделить вещи. Иногда я предпочитаю использовать отдельную переменную, потому что я могу определить длинный литерал в строке с вызовом команды.
function strcat() {
local IFS=""
echo -n "$*"
}
mycommand
--server myserver
--filename "$(strcat
extremely/long/file/name/
that/i/would/like/to/be/able/to/break/
up/if/possible)"
--otherflag
--anotherflag
Мне также нравится этот подход, когда мне нужно вводить длинный CSV значений в качестве параметра флага, потому что я могу использовать его, чтобы избежать ввода запятой между значениями:
function strjoin() {
local IFS="$1"
shift
echo -n "$*"
}
csv_args=(
foo=hello
bar=world
"this=arg has spaces in it"
)
mycommand
--server myserver
--csv_args "$(strjoin , "${csv_args[@]}")"
--otherflag
--anotherflag
Что эквивалентно
mycommand
--server myserver
--csv_args "foo=hello,bar=world,this=arg has spaces in it"
--otherflag
--anotherflag
Ответ №6:
Еще один способ записи длинной строки в переменную с сохранением максимальной длины строки:
printf -v fname '%s'
'extremely/long/file/name/that/i/'
'would/like/to/be/able/to/break/up/'
'if/possible'
Поскольку аргументов больше, чем директив форматирования, %s
просто повторяется, и мы получаем
$ declare -p fname
declare -- fname="extremely/long/file/name/that/i/would/like/to/be/able/to/break/up/if/possible"
который можно использовать как
mycommand
--server myserver
--filename "$fname"
--otherflag
--anotherflag
Это особенно удобно при настройке длинных переменных с изначально разделенным содержимым, таким как CDPATH
(или PATH
, конечно):
printf -v CDPATH '%s'
':/Users/benjamin/here/is/a/long/path'
':/Users/benjamin/and/here/is/another/one'
':/Users/benjamin/and/a/third/line'
export CDPATH
в отличие от
export CDPATH=':/Users/benjamin/here/is/a/long/path:/Users/benjamin/and/here/is/another/one:/Users/benjamin/and/a/third/line'
или неуклюжий
export CDPATH=':/Users/benjamin/here/is/a/long/path'
CDPATH =':/Users/benjamin/and/here/is/another/one'
CDPATH =':/Users/benjamin/and/a/third/line'