Jak mogę powtórzyć postać w Bash?

Jak mógłbym to zrobić z echo?

perl -E 'say "=" x 100'
Author: Mateusz Piotrowski, 2011-03-18

30 answers

Możesz użyć:

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

Jak to działa:

Bash rozszerza {1..Tak więc Komenda staje się:

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

Ustawiłem format printf na =%.0s, co oznacza, że zawsze wyświetli pojedynczy = bez względu na podany argument. Dlatego drukuje 100 =s.

 433
Author: dogbane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-18 09:28:11

To nie jest łatwe. Ale na przykład:

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

A może sposób zgodny ze standardem:

printf %100s |tr " " "="

Jest też tput rep, ale co do moich terminali pod ręką (xterm i linux) chyba go nie obsługują:)

 95
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-18 09:55:41

końcówka kapelusza do @gniourf_gniourf za jego wkład.

Uwaga: Ta odpowiedź nie odpowiada na pierwotne pytanie, ale uzupełnia istniejące, pomocne odpowiedzi przez porównując wydajność.

Rozwiązania są porównywane tylko pod względem szybkości wykonania - pod uwagę brane są wymagania pamięci , a nie (różnią się one w zależności od rozwiązań i mogą mieć znaczenie przy dużych powtórzeniach liczy).

Podsumowanie:

  • jeśli liczba powtórzeń jest mała, powiedzmy do około 100, to jest warto iść z rozwiązania tylko Bash, ponieważ koszt uruchamiania zewnętrznych narzędzi ma znaczenie, zwłaszcza Perla.
    • mówiąc pragmatycznie, jeśli jednak potrzebujesz tylko jednej instancji powtarzających się znaków, wszystkie istniejące rozwiązania mogą być w porządku.
  • Z duży powtórz liczy, użyj narzędzi zewnętrznych, ponieważ będą znacznie szybsze.
      W szczególności, unikaj globalnej wymiany podłańcucha Basha za pomocą dużych łańcuchów.]} (np., ${var// /=}), ponieważ jest on zbyt wolny.
[19]}poniżej przedstawiono timingi wykonane na iMacu z końca 2012 roku z procesorem Intel Core i5 3,2 GHz i dyskiem Fusion Drive, z systemem OSX 10.10.4 i bash 3.2.57, i są średnio 1000 uruchomień.

Wpisy są:

  • wymienione w rosnącej kolejności czas trwania wykonania (najszybszy pierwszy)
  • :
    • M ... a potencjalnie multi - rozwiązanie znakowe
    • S ... a single -rozwiązanie tylko dla znaków
    • P ... rozwiązanie zgodne ze standardem POSIX]}
  • po którym następuje krótki opis rozwiązania
  • przyrostkiem nazwiska autora odpowiedzi

  • Mały liczba powtórzeń: 100
[M, P] printf %.s= [dogbane]:                           0.0002
[M   ] printf + bash global substr. replacement [Tim]:  0.0005
[M   ] echo -n - brace expansion loop [eugene y]:       0.0007
[M   ] echo -n - arithmetic loop [Eliah Kagan]:         0.0013
[M   ] seq -f [Sam Salisbury]:                          0.0016
[M   ] jot -b [Stefan Ludwig]:                          0.0016
[M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.0019
[M, P] awk - while loop [Steven Penny]:                 0.0019
[S   ] printf + tr [user332325]:                        0.0021
[S   ] head + tr [eugene y]:                            0.0021
[S, P] dd + tr [mklement0]:                             0.0021
[M   ] printf + sed [user332325 (comment)]:             0.0021
[M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0025
[M, P] mawk - while loop [Steven Penny]:                0.0026
[M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0028
[M, P] gawk - while loop [Steven Penny]:                0.0028
[M   ] yes + head + tr [Digital Trauma]:                0.0029
[M   ] Perl [sid_com]:                                  0.0059
  • rozwiązania tylko Bash prowadzą watahę-ale tylko z liczbą powtórzeń tak małą! (patrz poniżej).
  • koszt uruchomienia zewnętrznych narzędzi ma tutaj znaczenie, szczególnie Perla. jeśli musisz wywołać to w pętli - z małymi powtórzeniami w każdej iteracji-unikaj rozwiązań multi-utility, awk i perl.

  • duża liczba powtórzeń: 1000000 (1 milion)
[M   ] Perl [sid_com]:                                  0.0067
[M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0254
[M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0599
[S   ] head + tr [eugene y]:                            0.1143
[S, P] dd + tr [mklement0]:                             0.1144
[S   ] printf + tr [user332325]:                        0.1164
[M, P] mawk - while loop [Steven Penny]:                0.1434
[M   ] seq -f [Sam Salisbury]:                          0.1452
[M   ] jot -b [Stefan Ludwig]:                          0.1690
[M   ] printf + sed [user332325 (comment)]:             0.1735
[M   ] yes + head + tr [Digital Trauma]:                0.1883
[M, P] gawk - while loop [Steven Penny]:                0.2493
[M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.2614
[M, P] awk - while loop [Steven Penny]:                 0.3211
[M, P] printf %.s= [dogbane]:                           2.4565
[M   ] echo -n - brace expansion loop [eugene y]:       7.5877
[M   ] echo -n - arithmetic loop [Eliah Kagan]:         13.5426
[M   ] printf + bash global substr. replacement [Tim]:  n/a
  • Perl rozwiązanie z pytania jest zdecydowanie najszybsze.
  • Bash ' s global string-replacement (${foo// /=}) jest niewytłumaczalnie potwornie powolny przy dużych strunach i został usunięty z biegu (zajęło około 50 minut(!)w Bash 4.3.30, a nawet dłużej w Bash 3.2.57 - nigdy nie czekałem na zakończenie).
  • Pętle Bash są wolne, a pętle arytmetyczne ((( i= 0; ... ))) są wolniejsze niż pętle rozszerzone nawiasami ({1..n}) - choć pętle arytmetyczne są bardziej wydajne w pamięci.
  • awk odnosi się do BSD awk (jak również na OSX) - jest zauważalnie wolniejszy niż gawk (GNU Awk), a szczególnie mawk.
  • zauważ, że z dużymi licznikami i wieloma znakami. ciągi, zużycie pamięci może stać się brane pod uwagę - podejścia różnią się pod tym względem.

Oto skrypt Bash (testrepeat) to spowodowało powyższe. Przyjmuje 2 argumenty:

  • liczba powtórzeń znaków
  • opcjonalnie, liczba przejazdów testowych do wykonania i do Oblicz średni czas od

Innymi słowy: powyższe timingi zostały uzyskane z testrepeat 100 1000 i testrepeat 1000000 1000

#!/usr/bin/env bash

title() { printf '%s:\t' "$1"; }

TIMEFORMAT=$'%6Rs'

# The number of repetitions of the input chars. to produce
COUNT_REPETITIONS=${1?Arguments: <charRepeatCount> [<testRunCount>]}

# The number of test runs to perform to derive the average timing from.
COUNT_RUNS=${2:-1}

# Discard the (stdout) output generated by default.
# If you want to check the results, replace '/dev/null' on the following
# line with a prefix path to which a running index starting with 1 will
# be appended for each test run; e.g., outFilePrefix='outfile', which
# will produce outfile1, outfile2, ...
outFilePrefix=/dev/null

{

  outFile=$outFilePrefix
  ndx=0

  title '[M, P] printf %.s= [dogbane]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In order to use brace expansion with a variable, we must use `eval`.
  eval "
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf '%.s=' {1..$COUNT_REPETITIONS} >"$outFile"
  done"

  title '[M   ] echo -n - arithmetic loop [Eliah Kagan]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    for ((i=0; i<COUNT_REPETITIONS; ++i)); do echo -n =; done >"$outFile"
  done


  title '[M   ] echo -n - brace expansion loop [eugene y]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In order to use brace expansion with a variable, we must use `eval`.
  eval "
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    for i in {1..$COUNT_REPETITIONS}; do echo -n =; done >"$outFile"
  done
  "

  title '[M   ] printf + sed [user332325 (comment)]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf "%${COUNT_REPETITIONS}s" | sed 's/ /=/g' >"$outFile"
  done


  title '[S   ] printf + tr [user332325]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf "%${COUNT_REPETITIONS}s" | tr ' ' '='  >"$outFile"
  done


  title '[S   ] head + tr [eugene y]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    head -c $COUNT_REPETITIONS < /dev/zero | tr '\0' '=' >"$outFile"
  done


  title '[M   ] seq -f [Sam Salisbury]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    seq -f '=' -s '' $COUNT_REPETITIONS >"$outFile"
  done


  title '[M   ] jot -b [Stefan Ludwig]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    jot -s '' -b '=' $COUNT_REPETITIONS >"$outFile"
  done


  title '[M   ] yes + head + tr [Digital Trauma]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    yes = | head -$COUNT_REPETITIONS | tr -d '\n'  >"$outFile"
  done

  title '[M   ] Perl [sid_com]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    perl -e "print \"=\" x $COUNT_REPETITIONS" >"$outFile"
  done

  title '[S, P] dd + tr [mklement0]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    dd if=/dev/zero bs=$COUNT_REPETITIONS count=1 2>/dev/null | tr '\0' "=" >"$outFile"
  done

  # !! On OSX, awk is BSD awk, and mawk and gawk were installed later.
  # !! On Linux systems, awk may refer to either mawk or gawk.
  for awkBin in awk mawk gawk; do
    if [[ -x $(command -v $awkBin) ]]; then

      title "[M   ] $awkBin"' - $(count+1)="=" [Steven Penny (variant)]'
      [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
      time for (( n = 0; n < COUNT_RUNS; n++ )); do 
        $awkBin -v count=$COUNT_REPETITIONS 'BEGIN { OFS="="; $(count+1)=""; print }' >"$outFile"
      done

      title "[M, P] $awkBin"' - while loop [Steven Penny]'
      [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
      time for (( n = 0; n < COUNT_RUNS; n++ )); do 
        $awkBin -v count=$COUNT_REPETITIONS 'BEGIN { while (i++ < count) printf "=" }' >"$outFile"
      done

    fi
  done

  title '[M   ] printf + bash global substr. replacement [Tim]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In Bash 4.3.30 a single run with repeat count of 1 million took almost
  # !! 50 *minutes*(!) to complete; n Bash 3.2.57 it's seemingly even slower -
  # !! didn't wait for it to finish.
  # !! Thus, this test is skipped for counts that are likely to be much slower
  # !! than the other tests.
  skip=0
  [[ $BASH_VERSINFO -le 3 && COUNT_REPETITIONS -gt 1000 ]] && skip=1
  [[ $BASH_VERSINFO -eq 4 && COUNT_REPETITIONS -gt 10000 ]] && skip=1
  if (( skip )); then
    echo 'n/a' >&2
  else
    time for (( n = 0; n < COUNT_RUNS; n++ )); do 
      { printf -v t "%${COUNT_REPETITIONS}s" '='; printf %s "${t// /=}"; } >"$outFile"
    done
  fi
} 2>&1 | 
 sort -t$'\t' -k2,2n | 
   awk -F $'\t' -v count=$COUNT_RUNS '{ 
    printf "%s\t", $1; 
    if ($2 ~ "^n/a") { print $2 } else { printf "%.4f\n", $2 / count }}' |
     column -s$'\t' -t
 59
Author: mklement0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:17

Jest na to więcej niż jeden sposób.

Korzystanie z pętli:

  • Rozszerzenie nawiasu może być używane z literałami całkowitymi:

    for i in {1..100}; do echo -n =; done    
    
  • Pętla podobna do C pozwala na użycie zmiennych:

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

Korzystanie z wbudowanego printf:

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

Podanie tutaj precyzji obcina łańcuch tak, aby pasował do podanej szerokości (0). Ponieważ printf Ponownie wykorzystuje łańcuch formatowania, aby pochłonąć wszystkie argumenty, to po prostu wydruki "=" 100 razy.

Za pomocą head (printf, itp) oraz tr:

head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="
 50
Author: Eugene Yarmash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-25 11:02:30

Znalazłem naprawdę łatwy sposób, aby to zrobić za pomocą seq:

Aktualizacja: to działa na BSD seq, który pochodzi z OS X. YMMV z innymi wersjami

seq  -f "#" -s '' 10

Wydrukuje ' # ' 10 razy, w ten sposób:

##########
  • -f "#" ustawia ciąg formatowania, aby ignorował Liczby i po prostu drukował # dla każdego z nich.
  • -s '' ustawia separator na pusty łańcuch, aby usunąć nowe linie, które seq wstawia między każdą liczbą
  • spacje po -f i -s wydają się być ważne.

EDIT: tutaj jest przydatna funkcja...

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

Które można tak nazwać...

repeat "#" 10

Uwaga: jeśli powtarzasz # to cytaty są ważne!

 33
Author: Sam Salisbury,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-30 00:54:19

Oto dwa ciekawe sposoby:

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

Zauważ, że te dwa są subtelnie różne-metoda paste kończy się nową linią. Metoda tr nie.

 23
Author: Digital Trauma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-21 15:37:02

Nie ma prostej drogi. Unikaj pętli za pomocą printf i substytucji.

str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.
 14
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-01 07:10:50

Pytanie było jak to zrobić z echo:

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

To zrobi dokładnie to samo co perl -E 'say "=" x 100', ale tylko z echo.

 10
Author: manifestor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-05 12:49:13

Jeśli chcesz mieć zgodność z POSIX i spójność pomiędzy różnymi implementacjami echo i printf i / lub powłokami innymi niż tylko 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)

...będzie produkować to samo wyjście co perl -E 'say "=" x 100' prawie wszędzie.

 9
Author: Geoff Nixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-03 14:58:34

Czysty sposób Bash Bez eval, bez podshellów, bez zewnętrznych narzędzi ,bez rozszerzeń nawiasów (np. możesz mieć liczbę do powtórzenia w zmiennej):

Jeśli otrzymamy zmienną n, która rozszerza się na (nieujemną) liczbę i zmienną pattern, np.

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

Możesz utworzyć funkcję za pomocą tego:

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}"
}

Z tym zestawem:

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

Do tej małej sztuczki używamy printf całkiem sporo:

  • -v varname: zamiast drukowania do standardu output, printf umieści zawartość sformatowanego łańcucha w zmiennej varname.
  • '%*s': printf użyje argumentu do wypisania odpowiedniej liczby spacji. Np. printf '%*s' 42 wydrukuje 42 spacje.
  • wreszcie, gdy mamy żądaną liczbę spacji w naszej zmiennej, używamy rozszerzenia parametru, aby zastąpić wszystkie przestrzenie naszym wzorem: ${var// /$pattern} rozszerzy się do rozszerzenia var z wszystkimi spacjami zastąpionymi rozszerzeniem $pattern.

Możesz także pozbądź się zmiennej tmp w funkcji repeat za pomocą rozszerzenia pośredniego:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    printf -v "$3" '%*s' "$1"
    printf -v "$3" '%s' "${!3// /$2}"
}
 8
Author: gniourf_gniourf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-01 09:15:45

Oto czego używam do drukowania linii znaków na ekranie w Linuksie (na podstawie szerokości terminala/ekranu)

Print " = " w poprzek ekranu:

printf '=%.0s' $(seq 1 $(tput cols))

Explanation:

Wypisuje znak równości tyle razy, ile podanej sekwencji:

printf '=%.0s' #sequence

Użyj wyjścia polecenia (jest to funkcja bash o nazwie zastępowanie poleceń):

$(example_command)

Podaj sekwencję, użyłem 1 do 20 jako przykład. W końcowym poleceniu zamiast polecenia tput 20:

seq 1 20

Podaj liczbę kolumn aktualnie używanych w terminalu:

tput cols
 8
Author: mattbell87,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
#!/usr/bin/awk -f
BEGIN {
  OFS = "="
  NF = 100
  print
}

Lub

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

Przykład

 7
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 05:51:10

Inny sposób powtórzenia dowolnego ciągu n razy:

Plusy:

  • Działa z powłoką POSIX.
  • wyjście może być przypisane do zmiennej.
  • powtarza dowolny ciąg znaków.
  • bardzo szybko, nawet z bardzo dużymi powtórzeniami.

Wady:

  • wymaga Komendy yes Gnu Core Utils.
#!/usr/bin/sh
to_repeat='='
repeat_count=80
yes "$to_repeat" | tr -d '\n' | head -c "$repeat_count"

Z terminalem ANSI i znakami US-ASCII do powtórzenia. Możesz użyć sekwencji ucieczki ANSI CSI. Jest to najszybszy sposób na powtórzenie charakter.

#!/usr/bin/env bash

char='='
repeat_count=80
printf '%c\e[%db' "$char" "$repeat_count"

Lub statycznie:

Wyświetla linię 80 razy =:

printf '=\e[80b\n'

Ograniczenia:

  • nie wszystkie terminale rozumieją repeat_char sekwencję ANSI CSI.
  • Tylko US-ASCII lub jednobajtowe znaki ISO mogą być powtarzane.
  • powtarzanie zatrzymuje się na ostatniej kolumnie, dzięki czemu można użyć dużej wartości do wypełnienia całego wiersza niezależnie od szerokości terminala.
  • powtórzenie jest tylko do wyświetlenia. Przechwytywanie danych wyjściowych do zmiennej powłoki nie rozszerzy się Sekwencja repeat_char ANSI CSI do powtarzającego się znaku.
 6
Author: Léa Gris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-12 17:04:20

W bash 3.0 lub wyższej

for i in {1..100};do echo -n =;done
 5
Author: loafoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-18 08:49:56

Domyślam się, że pierwotnym celem pytania było zrobienie tego tylko za pomocą wbudowanych poleceń powłoki. Więc for pętle i printf s byłyby uzasadnione, podczas gdy rep, perl, a także jot poniżej nie. Nadal, następujące polecenie

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

Na przykład wyświetla linię szerokości okna \/\/\/\/\/\/\/\/\/\/\/\/

 5
Author: Stefan Ludwig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-21 14:54:13

Jak mówili inni, w bash Rozszerzanie nawiasów poprzedza Rozszerzanie parametrów , więc zakresy {m,n} mogą zawierać tylko literały. seq oraz jot zapewnij czyste rozwiązania, ale nie są w pełni przenośne z jednego systemu do drugiego, nawet jeśli używasz tej samej powłoki na każdym z nich. (Chociaż {[3] } jest coraz bardziej dostępny; np. we FreeBSD 9.3 i wyższych .) eval i inne formy iniekcji zawsze działają, ale są nieco nieeleganckie.

Na szczęście bash obsługuje styl C dla pętli (tylko z wyrażeniami arytmetycznymi). Tak więc oto zwięzły" czysty bash " sposób:
repecho() { for ((i=0; i<$1; ++i)); do echo -n "$2"; done; echo; }

To bierze liczbę powtórzeń jako pierwszy argument i ciąg znaków do powtórzenia (który może być pojedynczym znakiem, jak w opisie problemu) jako drugi argument. repecho 7 b wyjścia bbbbbbb (zakończone znakiem nowej linii).

Dennis Williamson dał zasadniczo To rozwiązanie cztery lata temu w jego doskonała odpowiedź na Tworzenie ciągu powtarzających się znaków w skrypcie powłoki . Moje ciało funkcyjne różni się nieco od tamtejszego kodu:

  • Ponieważ skupiamy się na powtarzaniu pojedynczego znaku, a powłoką jest bash, prawdopodobnie można bezpiecznie używać echo zamiast printf. I przeczytałem opis problemu w tym pytaniu jako wyrażający preferencję drukowania za pomocą echo. Powyższa definicja funkcji działa w bash i ksh93. Chociaż printf jest składnia echo jest prawdopodobnie bardziej czytelna .

    Niektóre wbudowane powłoki echo interpretują - same w sobie jako opcję-mimo że zwykłe znaczenie -, aby używać standardowego wejścia, jest bezsensowne dla echo. Zsh robi to. I na pewno istnieją echo s, które nie rozpoznają -n, ponieważ nie jest to standardowe. (Wiele powłok w stylu Bourne ' a w ogóle nie akceptuje c-style dla pętli, stąd ich zachowanie echo nie trzeba tego brać pod uwagę..)

  • Tutaj zadaniem jest wypisanie sekwencji; tam , było przypisanie jej do zmiennej.

Jeśli $n jest pożądaną liczbą powtórzeń i nie musisz jej ponownie używać, a chcesz coś jeszcze krótszego:

while ((n--)); do echo -n "$s"; done; echo

n musi być zmienna--w ten sposób nie działa z parametrami pozycyjnymi. {[23] } jest tekstem do powtórzenia.

 5
Author: Eliah Kagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:38

Python jest wszechobecny i wszędzie działa tak samo.

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

Znak i liczba są przekazywane jako oddzielne parametry.

 4
Author: loevborg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-01 00:16:23

W przypadku, gdy chcesz powtórzyć znak N razy, czyli N zmienną liczbę razy w zależności np. od długości łańcucha, możesz to zrobić:

#!/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)

Wyświetla:

vari equals.............................: AB  
Up to 10 positions I must fill with.....: 8 equal signs  
AB========  
 2
Author: Raul Baron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-15 03:17:37
repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    printf -v "TEMP" '%*s' "$1"
    echo ${TEMP// /$2}
}
 2
Author: WSimpson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-31 15:44:34

To jest dłuższa wersja tego, co Eliah Kagan opowiadał:]}

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

Oczywiście możesz do tego również użyć printf, ale nie do końca mi się podoba:

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

Ta wersja jest kompatybilna z Dash:

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

Z i jako liczbą początkową.

 2
Author: Xennex81,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-02 23:33:26

Najprostszym jest użycie tej Jedynki w csh/tcsh:

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

 2
Author: Shawn Givler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-01 06:54:06

Inną opcją jest użycie GNU seq i usunięcie wszystkich liczb i nowych linii, które generuje:

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

To polecenie wyświetla znak # 100 razy.

 2
Author: sigalor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-07 13:53:04
for i in {1..100}
do
  echo -n '='
done
echo
 1
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-18 08:50:32
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
}

Przykładowe biegi

$ repeatString 'a1' 10 
a1a1a1a1a1a1a1a1a1a1

$ repeatString 'a1' 0 

$ repeatString '' 10 

Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

 1
Author: Nam Nguyen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-08 18:30:01
Jak mógłbym to zrobić z echo?

Możesz to zrobić za pomocą echo, Jeśli po echo następuje sed:

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

Właściwie, to echo jest tam niepotrzebne.

 1
Author: DaBler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-01 13:12:06

Moja odpowiedź jest nieco bardziej skomplikowana i prawdopodobnie nie idealna, ale dla tych, którzy chcą uzyskać duże liczby, byłem w stanie zrobić około 10 milionów w 3 sekundy.

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}
}
 1
Author: Silver Ogre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-23 07:50:20

Najprostszym jest użycie tej Jedynki w bashu:

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

 1
Author: shahin aref,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-27 06:54:43

Bardziej elegancką alternatywą dla proponowanego rozwiązania Pythona może być:

python -c 'print "="*(1000)'
 1
Author: Anas Tiour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-22 06:58:51

Większość istniejących rozwiązań zależy od {1..10} obsługi składni powłoki, która jest specyficzna dla bash - i zsh - i nie działa w tcsh ani w OpenBSD ksh i większość nie-bash sh.

Poniższe powinno działać na OS X i wszystkich systemach *BSD w dowolnej powłoce; w rzeczywistości może być użyte do wygenerowania całej macierzy różnych typów przestrzeni dekoracyjnych:

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

Niestety, nie otrzymujemy ciągłej nowej linii; która może być naprawiona przez dodatkowy printf '\n' po fold:

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

Bibliografia:

 1
Author: cnst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-13 18:56:10

Nie do stos-on, ale inne podejście czysto Bash wykorzystuje ${//} Zastępowanie tablic:

$ arr=({1..100})
$ printf '%s' "${arr[@]/*/=}"
====================================================================================================
 1
Author: dimo414,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-25 23:44:15