Come ripetere un paio di caratteri un paio di volte in bash?
-
26-09-2019 - |
Domanda
In uno script bash, devo includere lo stesso file parecchie volte di fila come argomento. In questo modo:
convert image.png image.png image.png [...] many_images.png
dove image.png
deve essere ripetuto un paio di volte.
C'è una scorciatoia bash per ripetere un modello?
Soluzione
Questo funziona con un dato intero (10 nell'esempio qui sotto).
$ 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
Può essere utilizzato anche con 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
Altri suggerimenti
È possibile farlo espansione delle parentesi graffe utilizzando:
convert image.png{,,} many_images.png
produrrà:
convert image.png image.png image.png many_images.png
espansione Brace ripeterà la stringa (s) prima (e dopo) le bretelle per ogni stringa separata da virgole all'interno delle parentesi producendo una stringa consiting del prefisso, la stringa separata da virgole e il suffisso; e separando le stringhe generate da uno spazio.
In questo caso la stringa separata da virgole tra i supporti e il suffisso sono stringhe vuote che produrranno la stringa image.png tre volte.
#!/bin/bash
function repeat {
for ((i=0;i<$2;++i)); do echo -n $1 " "; done
}
convert $(repeat image.png 3) many_images.png
Ecco una soluzione che utilizza le matrici ed è quindi robusto per le stringhe contenenti spazi, a capo etc.
declare -a images
declare -i count=5
for ((i=0; i<count; ++i))
do
images+=(image.png)
done
convert "${images[@]}" many_images.png
Questo lavoro potrebbe per voi:
convert $(printf "image.png %.s" {1..5}) many_images.png
Questo si ripeterà image.png
5 volte prima many_images.png
Per evitare lento codice che apre casi inutili di bash utilizzando $ (comando) o command
è possibile utilizzare espansione delle parentesi graffe.
Per ripetere un nome di file 3 volte fanno:
file="image.png"; convert "${file[0]"{1..3}"}" many_images.png
o una versione più controverso che utilizza una variabile per specificare il numero di nomi di file ripetuti:
n=10; file="image.png"; eval convert \"\${file[0]\"{1..$n}\"}\" many_images.png
Come funziona.
{file [0]} $ è uguale a $ file o $ {file}
Bash fa espansione delle graffe prima e quindi ha una sequenza simile:
${file[0]1} ${file[0]2} ${file[0]3}
Bash gentilmente ignorare questi numeri in più in modo da ottenere
${file[0]} ${file[0]} ${file[0]}
che semplifica al
${file} ${file} ${file}
e quindi
$file $file $file
Il che è quello che vogliamo.
POSIX 7 soluzione che ho trovato finora:
N=3
S="image.png "
printf "%${N}s" | sed "s/ /$S/g"
dal yes
, seq
e {1..3}
non sono POSIX.
Per il vostro esempio specifico:
N=
convert $(printf "%${N}s" | sed "s/ /image.png /g") many_images.png