如何在bash中分解极长的字符串文字?

时间:2011-10-11 16:00:13

标签: linux bash

我想在bash脚本中嵌入一个这样的长命令:

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

长文件名分解。

我可以这样做:

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

但它打破了流程。我会喜欢来写这个:

# 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

但这不起作用,因为它会破坏字符串文字。

有没有办法告诉bash打破字符串文字但忽略任何前导空格?

6 个答案:

答案 0 :(得分:50)

这是黑客的位,但这有效:

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

Bash连接相邻的字符串文字,因此我们利用它。例如,echo "hi" "there"打印hi thereecho "hi""there"打印hithere

它还利用了反引号运算符,以及一堆空格的计算结果为空的事实。

答案 1 :(得分:41)

您可以使用变量:

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

答案 2 :(得分:2)

我在bash脚本的顶部定义了一个简短的strcat函数,并使用内联调用来分解。我有时更喜欢使用单独的变量,因为我可以使用命令调用来定义长文字。

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 \

当我必须输入一个长CSV值作为标志参数时,我也喜欢这种方法,因为我可以使用它来避免在值之间键入逗号:

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 \

相当于

mycommand \
  --server myserver \
  --csv_args "foo=hello,bar=world,this=arg  has  spaces  in  it" \
  --otherflag \
  --anotherflag \

答案 3 :(得分:2)

还可以使用数组变量

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 :(得分:1)

基本上,bash中没有任何内容可以做到这一点 包装器通常比它的价值更麻烦,但是说,你可以尝试别名或功能,例如。 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

答案 5 :(得分:0)

将长字符串写入变量,同时保持最大行距不变的另一种方法:

printf -v fname '%s' \
    'extremely/long/file/name/that/i/' \
    'would/like/to/be/able/to/break/up/' \
    'if/possible'

因为参数多于格式指令,所以%s被重复了,我们得到了

$ declare -p fname
declare -- fname="extremely/long/file/name/that/i/would/like/to/be/able/to/break/up/if/possible"

使用方式

mycommand \
    --server myserver \
    --filename "$fname" \
    --otherflag \
    --anotherflag

在设置内容固有分隔的长变量(例如CDPATH(当然是PATH)时,这特别方便:

printf -v CDPATH '%s' \
    ':/Users/benjamin/here/is/a/long/path' \
    ':/Users/benjamin/and/here/is/another/one' \
    ':/Users/benjamin/and/a/third/line'
export CDPATH

相对于

export CDPATH=':/Users/benjamin/here/is/a/long/path:/Users/benjamin/and/here/is/another/one:/Users/benjamin/and/a/third/line'

或者笨拙的

export CDPATH=':/Users/benjamin/here/is/a/long/path'
CDPATH+=':/Users/benjamin/and/here/is/another/one'
CDPATH+=':/Users/benjamin/and/a/third/line'