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
精彩评论