Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split string across multiple lines in bash

A constant annoyance for me (minor, but constant) is that I can't (or don't know how) to split a string across multiple lines in bash code. What I have is this:

    while getopts 'd:h' argv; do
    case "${argv}" in
        d) local target_dir="${OPTARG}" ;;
        h)
           printf "Usage: remove_file_end_strings [ -d <work directory> ] <string to remove>\n"
           return 1
           ;;
    esac

Which looks OK here as there is no word wrapping, but when limited to 80 chars and wordwrapped looks very untidy. When what I want is something like this, which is simple in python or ruby:

    while getopts 'd:h' argv; do
    case "${argv}" in
        d) local target_dir="${OPTARG}" ;;
        h)
           printf "Usage: remove_file_end_strings [ -d <work "
                  "directory> ] <string to remove>\n"
           return 1
           ;;
    esac

My google-fu has let me down, so is there a way to achieve this in bash or am I just going to have to keep biting down hard on a block of wood? ta

edit: I've just about decided on my suboptimal solution:

    while getopts 'd:h' argv; do
    case "${argv}" in
        d) local target_dir="${OPTARG}" ;;
        h)
            printf "Usage: remove_file_end_strings [ -d <work "
            printf "directory> ] <string to remove>\n"
            return 1
            ;;
    esac
done
like image 923
spoovy Avatar asked Mar 13 '18 15:03

spoovy


People also ask

How do I create a multiline string in bash?

Bash Escape Characters For example, if we have a multiline string in a script, we can use the \n character to create a new line where necessary. Executing the above script prints the strings in a new line where the \n character exists.

How do I echo multiple lines in bash?

To add multiple lines to a file with echo, use the -e option and separate each line with \n. When you use the -e option, it tells echo to evaluate backslash characters such as \n for new line. If you cat the file, you will realize that each entry is added on a new line immediately after the existing content.


2 Answers

It's easy to break the line, but it's harder to not introduce any extra spaces or token boundaries when you indent the next line. Without indenting, it's simple but ugly:

{
    printf "Usage: remove_file_end_strings \
[ -d <work directory> ] <string to remove>\n"
}

For better or worse, echo is more sloppy in what it accepts:

echo 'This is my string'   \
     'that is broken over' \
     'multiple lines.'

This passes 3 arguments to echo instead of 1, but since the arguments are joined with spaces, it works out the same.

In your case, when you're putting the entire message in the format string, you can emulate the same behavior:

printf "%b " 'This is my string'    \
             'that again is broken' \
             'over multiple lines.\n'

Though obviously this doesn't work as well when you have a proper format string with different slots.

In such cases, there are hacks:

 printf "I am also split `
        `across %s `
        `lines\\n"  \
        "a number of"
like image 172
that other guy Avatar answered Oct 09 '22 04:10

that other guy


Using inline document with the <<- operator:

while getopts 'd:h' argv; do
    case "${argv}" in
            d) local target_dir="${OPTARG}" ;;
            h)
                    cat <<-EOT
                    Usage: remove_file_end_strings [ -d <work directory> ] <string to remove>
                    EOT
    esac
done

See man bash and look for Here Documents:

If the redirection operator is <<-, then all leading tab characters are stripped from input lines and the line containing delimiter. This allows here-documents within shell scripts to be indented in a natural fashion.

If a break in the line is required, pipe a sed command that will remove tabs in between the string:

while getopts 'd:h' argv; do
    case "${argv}" in
            d) local target_dir="${OPTARG}" ;;
            h)
                    cat <<-EOT | sed 's/\t*\([^\t]*\)/ \1/2g'
                    Usage: remove_file_end_strings [ -d <work \
                    directory> ] <string to remove>
                    EOT
    esac
done
like image 40
oliv Avatar answered Oct 09 '22 03:10

oliv