开发者

How to repeat a few characters a few times in bash?

In a bash sc开发者_JAVA技巧ript, I have to include the same file several times in a row as an argument. Like this:

convert image.png image.png image.png [...] many_images.png

where image.png should be repeated a few times.

Is there a bash shorthand for repeating a pattern?


You can do this using brace expansion:

convert image.png{,,} many_images.png

will produce:

convert image.png image.png image.png many_images.png

Brace expansion will repeat the string(s) before (and after) the braces for each comma-separated string within the braces producing a string consiting of the prefix, the comma-separated string and the suffix; and separating the generated strings by a space.

In this case the comma-separated string between the braces and the suffix are empty strings which will produce the string image.png three times.


This works with a given integer (10 in the example below).

$ echo $(yes image.png | head -n10)
image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png

It can also be used with xargs:

$ yes image.png | head -n10 | xargs echo
image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png


#!/bin/bash

function repeat {
    for ((i=0;i<$2;++i)); do echo -n $1 " "; done
}

convert $(repeat image.png 3) many_images.png


Here is a solution that uses arrays and is thus robust for strings containing spaces, newlines etc.

declare -a images
declare -i count=5
for ((i=0; i<count; ++i))
do
    images+=(image.png)
done
convert "${images[@]}" many_images.png


This might work for you:

convert $(printf "image.png %.s" {1..5}) many_images.png

This will repeat image.png 5 times before many_images.png


To avoid slow code that opens unnecessary instances of bash using $(command) or command you can use brace expansion.

To repeat a filename 3 times do:

file="image.png"; convert "${file[0]"{1..3}"}" many_images.png

or a more controversial version that uses a variable to specify number of repeated file names:

n=10; file="image.png"; eval convert \"\${file[0]\"{1..$n}\"}\" many_images.png

How it works.

${file[0]} is same as $file or ${file}

Bash does brace expansion first and so it makes up a sequence like this:

${file[0]1} ${file[0]2} ${file[0]3}

Bash kindly ignore these extra numbers so you get

${file[0]} ${file[0]} ${file[0]}

Which simplifies to

${file} ${file} ${file}

and then

$file $file $file

Which is what we want.


Shortest POSIX 7 solution I have found so far:

N=3
S="image.png "
printf "%${N}s" | sed "s/ /$S/g"

since yes, seq and {1..3} are not POSIX.

For your specific example:

N=
convert $(printf "%${N}s" | sed "s/ /image.png /g") many_images.png
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜