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!

  • 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 '15 at 11:59
  • Yes, the string could be for example an URL – ferhtgoldaraz Apr 12 '15 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. – Jonathan Leffler Apr 12 '15 at 14:45
  • Arbitrarily long, though my use cases are not that extreme – ferhtgoldaraz Apr 12 '15 at 16:21
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?

  • 1
    Make sure you quote your "$vars" unless you want word splitting and filename generation on the values. – glenn jackman Apr 12 '15 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 – ferhtgoldaraz Apr 12 '15 at 12:31
  • yes += works with bash for appending strings. – glenn jackman Apr 12 '15 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"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.