Как разбить очень длинный строковый литерал в bash? - программирование

Как разбить очень длинный строковый литерал в bash?

Я хотел бы вставить длинную команду, подобную этой, в bash script:

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 сломать строковый литерал, но игнорировать любые ведущие пробелы?

4b9b3361

Ответ 1

Вы можете использовать переменную:

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

Ответ 2

Это бит , но это работает:

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.

Он также использует преимущество оператора backtick и тот факт, что пучок пространств ничего не оценивает.

Ответ 3

Я определяю короткую функцию strcat в верхней части моего bash script и использую встроенный вызов для разделения вещей. Я иногда предпочитаю использовать отдельную переменную, потому что я могу определить длинный литерал в строке с вызовом команды.

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 \

Ответ 4

В принципе, для bash в нем ничего нет. Обертка, как правило, больше проблем, чем того стоит, но это говорит о том, что вы можете попробовать псевдоним или funciton, например. 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

Можно также использовать переменную массива

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