How do I break up an extremely long string literal

2020-05-13 12:40发布

I would like to embed a long command like this in a bash script:

mycommand \
    --server myserver \
    --filename extremely/long/file/name/that/i/would/like/to/be/able/to/break/up/if/possible \
    --otherflag \
    --anotherflag

with the long filename broken up.

I could do this:

# Insufficiently pretty
mycommand \
    --server myserver \
    --filename extremely/long/file/name/\
that/i/would/like/to/be/able/to/break/\
up/if/possible \
    --otherflag \
    --anotherflag \

but it breaks the flow. I would like to be able to write this:

# 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

but that doesn't work because it breaks up the string literal.

Is there a way to tell bash to break a string literal but ignore any leading spaces?

标签: linux bash
5条回答
别忘想泡老子
2楼-- · 2020-05-13 13:31

You can use a variable :

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
查看更多
你好瞎i
3楼-- · 2020-05-13 13:33

One can also use an array variable

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楼-- · 2020-05-13 13:38

I define a short strcat function at the top of my bash script and use an inline invocation to split things up. I sometimes prefer it to using a separate variable because I can define the long literal in-line with the command invocation.

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 \

I also like this approach for when I have to enter a long CSV of values as a flag parameter because I can use it to avoid typing the comma between values:

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 \

Which is equivalent to

mycommand \
  --server myserver \
  --csv_args "foo=hello,bar=world,this=arg  has  spaces  in  it" \
  --otherflag \
  --anotherflag \
查看更多
我命由我不由天
5楼-- · 2020-05-13 13:39

It's a bit of a hack, but this works:

mycommand \
    --server myserver \
    --filename "extremely/long/file/name/"`
               `"that/i/would/like/to/be/able/to/break/"`
               `"up/if/possible" \
    --otherflag \
    --anotherflag

Bash concatenates string literals that are adjacent, so we take advantage of that. For example, echo "hi" "there" prints hi there whereas echo "hi""there" prints hithere.

It also takes advantage of the backtick operator, and the fact that a bunch of spaces evaluates to nothing.

查看更多
时光不老,我们不散
6楼-- · 2020-05-13 13:43

Basically, there is nothing built into bash to do this.
A wrapper is typically more trouble than it's worth, but that said, you could try an alias or a funciton, eg. 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
查看更多
登录 后发表回答