web-dev-qa-db-fra.com

Comment puis-je répéter un personnage dans Bash?

Comment pourrais-je faire cela avec echo?

Perl -E 'say "=" x 100'
181
sid_com

Vous pouvez utiliser:

printf '=%.0s' {1..100}

Comment ça marche:

Bash se développe {1..100} pour que la commande devienne:

printf '=%.0s' 1 2 3 4 ... 100

J'ai défini le format de printf sur =%.0s, ce qui signifie qu'il imprimera toujours un seul =, quel que soit l'argument donné. Par conséquent, il imprime 100 =s.

307
dogbane

Pas facile. Mais par exemple:

seq -s= 100|tr -d '[:digit:]'

Ou peut-être une manière conforme aux normes:

printf %100s |tr " " "="

Il y a aussi un tput rep, mais mes terminaux (xterm et linux) ne semblent pas le supporter :)

75
user332325

Il y a plus d'une façon de le faire. 

Utilisation d'une boucle:

  • Le développement d'accolade peut être utilisé avec des littéraux entiers:

    for i in {1..100}; do echo -n =; done    
    
  • Une boucle de type C permet l'utilisation de variables: 

    start=1
    end=100
    for ((i=$start; i<=$end; i++)); do echo -n =; done
    

Utilisation de la variable printf:

printf '=%.0s' {1..100}

Spécifier une précision ici tronque la chaîne pour l'adapter à la largeur spécifiée (0). Comme printf réutilise la chaîne de format pour utiliser tous les arguments, ceci imprime simplement "=" 100 fois.

Utilisation de head (printf, etc.) et de tr:

head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="
38
Eugene Yarmash

Je viens de trouver un moyen très simple de faire cela en utilisant seq:

UPDATE: Ceci fonctionne sur la BSD seq fournie avec OS X. YMMV avec d'autres versions

seq  -f "#" -s '' 10

Imprimera '#' 10 fois, comme ceci:

##########
  • -f "#" définit la chaîne de formatage pour ignorer les nombres et imprimer # pour chacun.
  • -s '' définit le séparateur sur une chaîne vide pour supprimer les nouvelles lignes insérées par seq entre chaque nombre
  • Les espaces après -f et -s semblent être importants.

EDIT: Le voici dans une fonction pratique ...

repeat () {
    seq  -f $1 -s '' $2; echo
}

Que vous pouvez appeler comme ça ...

repeat "#" 10

NOTE: Si vous répétez #, les guillemets sont importants!

25
Sam Salisbury

Voici deux façons intéressantes:

 ubuntu @ ubuntu: ~ $ yes = | tête -10 | paste -s -d '' -
 ========== 
 ubuntu @ ubuntu: ~ $ yes = | tête -10 | tr -d "\ n" 
 ========== ubuntu @ ubuntu: ~ $ 

Notez que ces deux éléments sont légèrement différents. La méthode paste se termine par une nouvelle ligne. La méthode tr ne le fait pas.

16
Digital Trauma

Il n'y a pas de moyen simple. Évitez les boucles utilisant printf et la substitution.

str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.
11
Tim
#!/usr/bin/awk -f
BEGIN {
  OFS = "="
  NF = 100
  print
}

Ou

#!/usr/bin/awk -f
BEGIN {
  while (z++ < 100) printf "="
}

Exemple

7
Steven Penny

Si vous souhaitez une conformité et une cohérence POSIX entre les différentes implémentations de echo et printf et/ou de shells autres que bash:

seq(){ n=$1; while [ $n -le $2 ]; do echo $n; n=$((n+1)); done ;} # If you don't have it.

echo $(for each in $(seq 1 100); do printf "="; done)

... produira le même résultat que Perl -E 'say "=" x 100' un peu partout.

5
Geoff Nixon

Je suppose que le but initial de la question était de le faire uniquement avec les commandes intégrées du shell. Ainsi, for boucles et printfs seraient légitimes, alors que rep, Perl et jot ci-dessous ne le seraient pas. Pourtant, la commande suivante

jot -s "/" -b "\\" $((COLUMNS/2))

par exemple, imprime une ligne de \/\/\/\/\/\/\/\/\/\/\/\/ dans toute la fenêtre

4
Stefan Ludwig

Une manière pure de Bash sans eval, aucun sous-shell, aucun outil externe, aucune extension d'accolade (c'est-à-dire que vous pouvez avoir le nombre à répéter dans une variable):

Si on vous donne une variable n qui se développe en un nombre (non négatif) et une variable pattern, par exemple,

$ n=5
$ pattern=hello
$ printf -v output '%*s' "$n"
$ output=${output// /$pattern}
$ echo "$output"
hellohellohellohellohello

Vous pouvez créer une fonction avec ceci:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    local tmp
    printf -v tmp '%*s' "$1"
    printf -v "$3" '%s' "${tmp// /$2}"
}

Avec cet ensemble:

$ repeat 5 hello output
$ echo "$output"
hellohellohellohellohello

Pour cette petite astuce, nous utilisons beaucoup printf avec:

  • -v varname: au lieu d’imprimer sur une sortie standard, printf mettra le contenu de la chaîne formatée dans la variable varname.
  • '% * s': printf utilisera l'argument pour imprimer le nombre d'espaces correspondant. Par exemple, printf '%*s' 42 imprimera 42 espaces.
  • Enfin, lorsque nous avons le nombre d'espaces souhaité dans notre variable, nous utilisons un paramètre expansion pour remplacer tous les espaces par notre modèle: ${var// /$pattern} passera à l'extension var, tous les espaces étant remplacés par l'extension $pattern.

Vous pouvez également vous débarrasser de la variable tmp de la fonction repeat en utilisant l’extension indirecte:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    printf -v "$3" '%*s' "$1"
    printf -v "$3" '%s' "${!3// /$2}"
}
3
gniourf_gniourf
repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    printf -v "TEMP" '%*s' "$1"
    echo ${TEMP// /$2}
}
2
WSimpson

En bash 3.0 ou supérieur

for i in {1..100};do echo -n =;done
2
adnans
for i in {1..100}
do
  echo -n '='
done
echo
2

La question était de savoir comment le faire avec echo:

echo -e ''$_{1..100}'\b='

Cela fera exactement la même chose que Perl -E 'say "=" x 100' mais avec echo seulement.

1
chevallier

Voici la version la plus longue de ce qu'Eliah Kagan épousait:

while [ $(( i-- )) -gt 0 ]; do echo -n "  "; done

Bien sûr, vous pouvez utiliser printf pour cela aussi, mais pas vraiment à mon goût:

printf "%$(( i*2 ))s"

Cette version est compatible Dash:

until [ $(( i=i-1 )) -lt 0 ]; do echo -n "  "; done

avec i étant le nombre initial.

1
Xennex81

Une alternative plus élégante à la solution Python proposée pourrait être:

python -c 'print "="*(1000)'
1
Anas Tiour

Comment pourrais-je faire cela avec écho?

Vous pouvez le faire avec echo si la echo est suivie de sed:

echo | sed -r ':a s/^(.*)$/=\1/; /^={100}$/q; ba'

En fait, cette echo n'est pas nécessaire ici.

1
DaBler

Si vous souhaitez répéter un caractère n fois, n étant un nombre VARIABLE selon, par exemple, la longueur d'une chaîne, vous pouvez effectuer: 

#!/bin/bash
vari='AB'
n=$(expr 10 - length $vari)
echo 'vari equals.............................: '$vari
echo 'Up to 10 positions I must fill with.....: '$n' equal signs'
echo $vari$(Perl -E 'say "=" x '$n)

Il affiche:

vari equals.............................: AB  
Up to 10 positions I must fill with.....: 8 equal signs  
AB========  
1
Raul Baron

Une autre option consiste à utiliser GNU seq et à supprimer tous les nombres et toutes les lignes qu'il génère:

seq -f'#%.0f' 100 | tr -d '\n0123456789'

Cette commande imprime le caractère # 100 fois.

0
sigalor

La plupart des solutions existantes dépendent toutes du support de la syntaxe {1..10} du shell, qui est spécifique à bash et zsh et ne fonctionne pas dans tcsh ou OpenBSD ksh et la plupart des non-bash sh.

Ce qui suit devrait fonctionner sous OS X et tous les systèmes * BSD de n’importe quel shell; en fait, il peut être utilisé pour générer toute une matrice de différents types d’espaces décoratifs:

$ printf '=%.0s' `jot 64` | fold -16
================
================
================
================$ 

Malheureusement, nous n’avons pas de nouvelle ligne; qui peut être corrigé par un printf '\n' supplémentaire après le pli:

$ printf "=%.0s" `jot 64` | fold -16 ; printf "\n"
================
================
================
================
$ 

Références:

0
cnst

Python est omniprésent et fonctionne partout de la même manière.

python -c "import sys; print('*' * int(sys.argv[1]))" "=" 100

Caractère et nombre sont passés en tant que paramètres séparés.

0
loevborg

Ma réponse est un peu plus compliquée et probablement pas parfaite, mais pour ceux qui cherchent à produire de grands nombres, j'ai pu faire environ 10 millions en 3 secondes.

repeatString(){
    # argument 1: The string to print
    # argument 2: The number of times to print
    stringToPrint=$1
    length=$2

    # Find the largest integer value of x in 2^x=(number of times to repeat) using logarithms
    power=`echo "l(${length})/l(2)" | bc -l`
    power=`echo "scale=0; ${power}/1" | bc`

    # Get the difference between the length and 2^x
    diff=`echo "${length} - 2^${power}" | bc`

    # Double the string length to the power of x
    for i in `seq "${power}"`; do 
        stringToPrint="${stringToPrint}${stringToPrint}"
    done

    #Since we know that the string is now at least bigger than half the total, grab however many more we need and add it to the string.
    stringToPrint="${stringToPrint}${stringToPrint:0:${diff}}"
    echo ${stringToPrint}
}
0
Silver Ogre

Le plus simple est d'utiliser ce one-liner dans bash:

seq 10 | xargs -n 1 | xargs -I {} echo -n  ===\>;echo

0
shahin aref
function repeatString()
{
    local -r string="${1}"
    local -r numberToRepeat="${2}"

    if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
    then
        local -r result="$(printf "%${numberToRepeat}s")"
        echo -e "${result// /${string}}"
    fi
}

Échantillons

$ repeatString 'a1' 10 
a1a1a1a1a1a1a1a1a1a1

$ repeatString 'a1' 0 

$ repeatString '' 10 

Référence lib à: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

0
Nam Nguyen

Le plus simple est d'utiliser ce one-liner dans csh/tcsh:

printf "%50s\n" '' | tr '[:blank:]' '[=]'

0
Shawn Givler