6

I want to tidy up some script with long commands, so that for example:

{ somecheck || somecomand "reallyreallyreallyreallyreallyreallylongstring" } &> /dev/null &

becomes something like:

{ somecheck ||                   \
    somecomand "reallyreally"    \
        "reallyreally"           \
        "reallyreally"           \
        "longstring"             \
} &> /dev/null &

But I'm worried about word splitting. To avoid it, I'm considering this:

{ somecheck ||                   \
    somecomand  "$(echo          \
        "reallyreally"           \
        "reallyreally"           \
        "reallyreally"           \
        "longstring"             \
    )"                           \
} &> /dev/null &

Does any one know some other way to do multiline strings in bash/zsh? I'm having trouble googling for this info, and I think this'll mean at least three processes (the script, the background block, and the command substitution subshell); Maybe there's a better way?

Thanks in advance!

4
  • Just to clarify, you don't actually want multiline strings right? The whole issue is to not include the newlines in the string but use them only for readability, is that correct?
    – terdon
    Apr 12, 2015 at 11:59
  • Yes, the string could be for example an URL Apr 12, 2015 at 12:02
  • How long is "really long"? At work, we have a program where the command line (which is mostly machine-generated) is encroaching on a 128 KiB limit, and of the nearly 200 arguments, one is over 100 KiB. That's extremely long by any reasonable definition. It's hard to copy'n'paste that for analysis. Apr 12, 2015 at 14:45
  • Arbitrarily long, though my use cases are not that extreme Apr 12, 2015 at 16:21

3 Answers 3

6

Using line continuations like that adds spaces into your string: the sequence backslash-newline-whitespace will be replaced by a single space.

Just using a variables will go a long way towards improved readability:

url="reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongstring"
{ somecheck || somecomand "$url" } &> /dev/null &

You can still break that up into substrings, using an array

parts=(
    "reallyreallyreallyreally"
    "reallyreallyreallyreally"
    "reallyreallyreallyreally"
    "reallyreallyreallyreally"
    "longstring"
)
whole=$(IFS=; echo "${parts[*]}")

but is it that important to split up literal strings given the added complexity?

3
  • 1
    Make sure you quote your "$vars" unless you want word splitting and filename generation on the values. Apr 12, 2015 at 12:28
  • Will do. Also regarding the array solution, I seem to be able to concat strings: var="foo"; var+="bar"; echo $var. Is that zsh only or does it work with bash 4? Thanks for everything by the way Apr 12, 2015 at 12:31
  • yes += works with bash for appending strings. Apr 12, 2015 at 17:21
2

Well, you could simplify it slightly to:

$ [ -f /dev/null ] || sed 's/a/A/g' <(echo "thisis""avery"\
"long""string"\
"Ihave""separated"\
"into""smaller"\
"substrings")
thisisAverylongstringIhAvesepArAtedintosmAllersubstrings

The important point is to not have any extra whitespace in the input string, so no spaces around the \.

Glenn's suggestion to use variables is both prettier and simpler though, go with that.

0

I suggest an approach that is halfway between glenn's two suggestions: use a (simple, scalar) variable, but break its definition into multiple lines:

myword="super"
myword="${myword}cali"
myword="${myword}fragil"
myword="${myword}istic"
myword="${myword}expi"
myword="${myword}ali"
myword="${myword}docious"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .