如何在bash中将字符串跨多行拆分

6

对我来说(虽然是小问题,但持续存在的问题)的一个不断困扰是,在bash代码中我不能(或者不知道如何)将字符串跨多行拆分。以下是我的一段代码:

    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

这里看起来还不错,因为没有换行,但是当限制在80个字符并自动换行时,显得非常凌乱。 我想要的是像Python或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

我的谷歌搜索技巧已经让我失望了,有没有一种方法可以在bash中实现这个目标,或者我只能继续咬着木块努力了呢?

编辑:我已经决定采用次优解:

    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

请在您的帖子中添加样例输入和样例输出,使用代码标签。 - RavinderSingh13
我的问题与输入或输出无关,而是与代码本身的格式有关。 - spoovy
2个回答

10

打破行很容易,但是当您缩进下一行时,不引入任何额外的空格或标记边界却更难。不缩进很简单,但很丑陋:

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

不管好坏,echo函数在接受参数方面更加宽松:

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

这将3个参数传递给echo而不是1个,但由于这些参数是用空格连接的,因此结果相同。

在您的情况下,当您将整个消息放入格式字符串中时,您可以模拟相同的行为:

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

当你有一个包含不同插槽的合适格式字符串时,显然这种方法效果不佳。

在这种情况下,可以使用一些技巧:

 printf "I am also split `
        `across %s `
        `lines\\n"  \
        "a number of"

1
嗯,我知道echo方法,但通常我不使用它,因为在我的许多用例中需要更复杂的格式化或变量扩展。无论如何,还是谢谢。 - spoovy

5
使用带有<<-运算符的内联文档:
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

请参考man bash的“Here Documents”部分:
如果重定向操作符是<<-,则输入行中所有前导制表符都将被剥离,包括包含定界符的行。这使得在shell脚本中使用here-document可以以自然的方式缩进。
如果需要在行内换行,请使用管道运算符和一个sed命令来删除字符串之间的制表符:
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

那不是只是左对齐所有内容吗?我想要保留缩进。 - spoovy
谢谢,但这仍然不是我要问的。这会将所有文本放在一行上,传递80个字符。如果我像你一样添加第二行,换行符将包含在输出中。 - spoovy
1
好的,尽管我永远不会在现实中这样做,但我将其标记为已回答。因为从技术上讲它是有效的。而且你很有毅力,我得承认! :) - spoovy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接