Comando do Linux para repetir uma string n vezes


71

Existe algum comando interno do Linux que permita gerar uma string n vezes uma string de entrada?


11
Por "comando linux embutido", presumo que você queira dizer comando shell, e como você não menciona qual shell está usando, presumo que seja bash. Você pode verificar isso digitando "echo $ SHELL" na linha de comando e deverá obter algo semelhante a "/ bin / bash" de volta. Caso contrário, edite sua resposta para especificar o que ela mostra. Cheers :)
Adrian Petrescu

7
Marquei a pergunta com "bash". Eu pensei que isso seria suficiente.
GetFree

Respostas:


75
adrian@Fourier:~$ printf 'HelloWorld\n%.0s' {1..5}
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$

3
Você poderia explicar como isso funciona? Eu entendo o comando printf, pois é o mesmo que o do C / C ++. Mas não entendo como o {1..5} é expandido e como isso funciona em conjunto com a parte "% .0s".
GetFree

4
É um pouco complicado :) Tente executar "printf 'HelloWorld% d \ n' 1 2 3 4 5" e provavelmente clique para você. O sinalizador% .0s não deve fazer nada, apenas estar presente para captar argumentos. Então, se o bash obtiver mais argumentos do que especificadores de formato, simplesmente imprimirá várias cópias, pegando quantas forem necessárias. Então você obtém o efeito. A saída de "printf 'HelloWorld% d% d \ n' 1 2 3 4 5 6" provavelmente torna isso ainda mais claro. Espero que isto ajude!
Adrian Petrescu

Eu vejo. É o comportamento particular de printf o que permite a repetição
GetFree

11
(Devo observar que, do ponto de vista puramente teórico, esta é provavelmente a solução mais rápida, pois usa uma única primitiva de shell - e não processos externos. Na realidade, porém, vamos admitir, o desempenho de scripts bash não importa: )
Adrian Petrescu

11
O que é específico printfé que ele aplicará repetidamente argumentos em excesso à string de formato, "fazendo loop" gratuitamente. Por "excesso", quero dizer que existem mais argumentos do que %espaços reservados.
Dennis Williamson

69

Aqui está uma maneira antiquada que é bastante portátil:

yes "HelloWorld" | head -n 10

Esta é uma versão mais convencional da resposta de Adrian Petrescu usando a expansão de chaves:

for i in {1..5}
do
    echo "HelloWorld"
done

Isso é equivalente a:

for i in 1 2 3 4 5

Esta é uma versão um pouco mais concisa e dinâmica da resposta de pike :

printf -v spaces '%*s' 10 ''; printf '%s\n' ${spaces// /ten}

Como você se livra das novas linhas ao usar o comando yes?
GetFree

3
Uma maneira é canalizá-la sed -n 'H;${x;s/\n//gp}'ou sed -n ':t;${s/\n//gp};N;bt'outra é fazer o echo $(yes "HelloWorld" | head -n 10)que adiciona um espaço entre cada cópia da string. Ainda outra maneira é canalizá-lo através do tr -d '\n'qual também elimina a nova linha final.
Dennis Williamson

2
É como Haskell em uma concha: Hashell?
wchargin

4
A solução yes é bem organizada
piggybox

A yessolução era exatamente o que eu precisava, pois queria duplicar um comando (cuja saída varia). Assim:yes "$(my-command)" | head -n 2
arnsholt

14

Isso pode ser parametrizado e não requer uma variável temp, FWIW:

printf "%${N}s" | sed 's/ /blah/g'

Ou, se $Né o tamanho de uma matriz bash:

echo ${ARR[@]/*/blah}

3
Este é o mais curto POSIX 7 solução que eu tenho visto até agora uma vez seq, yese {1..5}não são POSIX 7.
Ciro Santilli新疆改造中心法轮功六四事件

Você não deve misturar dados no printfespecificador de formato. E se os dados contiverem seqüências de caracteres de formato? Esta é a maneira correta de especificar dinamicamente a "precisão" (comprimento): printf '%*s' "$N"- crie o hábito de incluir a seqüência de caracteres de formato entre aspas simples para impedir a expansão de variáveis ​​lá.
Dennis Williamson

13

Algumas boas maneiras já mencionadas. Não se pode esquecer os bons velhos seqtempos:

[john @ awesome] $ para i no `seq 5`; faça eco "Oi"; pronto
Oi
Oi
Oi
Oi
Oi

Este realmente respeita um zero, tratando-o como zero! (O {i..j}truque nunca retorna uma faixa vazia.)
JellicleCat

10

Talvez outra maneira que seja mais geral e útil para você:

adrian@Fourier:~$ n=5
adrian@Fourier:~$ for (( c=1; c<=n; c++)) ; do echo "HelloWorld" ; done
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld
adrian@Fourier:~$ 

O shell bash é mais poderoso do que a maioria das pessoas pensa :)


Isso recebe meu voto, pois é totalmente interno da shell; sem necessidade de bifurcação.
esm 23/12/09

2
A que bifurcação você está se referindo? A resposta original não requer nenhuma. A saída de 'type printf' é 'printf é um shell embutido' e, portanto, é executada no processo original do bash.
precisa saber é o seguinte

Este é o único até agora ( yes, printf, for i in {1..5}) que se o né zero, ele retorna string vazia, sem existir estatuto de 1. Também devido à notação matemática para comparação, é fácil ter compensado por 1 (por exemplo, mudando o <=para <)
Mehrad Mahmoudian 19/06

10

Você pode usar um truque. Fazer eco de uma variável vazia não imprime nada. Então você pode escrever:

echo word$wojek{1..100}

Se $wojek1 $wojek2... $wojek100são variáveis ​​inexistentes, você repetirá sua palavra 100 vezes sem mais nada.


11
É um truque feio e feio, e ainda assim não posso deixar de amá-lo e usá-lo.
16807

Adoro! Talvez o uso em $_vez de $wojektorne a intenção mais clara.
Mihai Todor

7

Repita os ntempos, basta colocar n-1vírgulas entre {}:

$ echo 'helloworld'{,,}
helloworld helloworld helloworld

Repete 'helloworld' duas vezes após o primeiro eco.


5
Legal, mas e se eu quiser obter nde uma variável?
GetFree

11
-lo adicionar um espaço extra após cada 'helloworld'
PADYMKO

isso não parece permitir que você coloque novas linhas na string (ou seja, obter helloworld em suas próprias linhas)
TankorSmash

5
awk 'BEGIN {while (c++<4) printf "Hello"}'

Resultado

Olá Olá Olá Olá

Use isso sem o awk: while ((c ++ <5)); faça printf 'olá'; done
emf 21/02

4

Eu experimentei avisos de tubos quebrados com a yessolução, então aqui está outra boa alternativa:

$ seq 4 | sed "c foo"
foo
foo
foo
foo

3

com base no que @pike estava sugerindo

para cada caractere na string eco da string

echo ${target//?/$replace}

Um exemplo de cabeçalho sublinhado com =caracteres

export heading='ABCDEF'; 
export replace='='; 
echo -e "${heading}\n${heading//?/$replace}"

irá produzir

ABCDEF
======

Isso parece estar entre o linux e o OS X e isso me deixa feliz.

nJoy!


3

Se você está no BSD, pode simplesmente usar seq.

$ seq -f "Hello, world" 5
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world

11
Em seq (GNU coreutils) 8.25, isso fornece seq: format 'Hello, world' has no % directive, forçando uma diretiva de formatação para estar presente. Coreutils GNU são usados, por exemplo, em muitas distribuições Linux e Cygwin. Incluindo a informação aqui para aqueles que não possuem a informação de que ela funciona apenas no BSD seq.
Palec

2
line="==========================="
line=${line:0:10}
${line//"="/"ten "}

saídas

ten ten ten ten ten ten ten ten ten ten

Talvez um exemplo mais detalhado: declare c = '-----'; c = $ {c // $ {c: 0: 1} / $ c}; eco $ c # Imprime "-" 25 vezes.
Stephen Niedzielski

2

Supondo que você queira algo como o xoperador de Perl , onde você não obtém automaticamente uma nova linha entre repetições:

x() {
  # usage: x string num
  for i in $(seq 1 $2); do printf "%s" "$1"; done
  # print a newline only if the string does not end in a newline
  [[ "$1" == "${1%$'\n'}" ]] && echo ""
}

x Hi 10  # ==> HiHiHiHiHiHiHiHiHiHi

x $'Hello World!\n' 3

Eu usei explicitamente um forloop porque você não pode escrever {1..$n}no bash: a expansão de chaves é feita antes da substituição de variáveis.


2

Não é exatamente embutido no linux, mas se você tem o python instalado ..

python
>>>var = "string"
>>>var*n

Ou em uma linha, como sugeriu o comentarista:

python -c 'print "This is a test.\n" * 10'

4
Não é realmente tão útil, já que não pode ser facilmente integrado aos scripts do shell, etc. .
Adrian Petrescu

7
Estou de acordo com o seu segundo ponto, mas não o punho ... é fácil de integrar em um script shell: python -c 'print ' Este é um teste \ n' * 10'
larsks

Eu gosto da legibilidade desta solução, uma boa razão suficiente para mim. ;)
elias

2

Não há mágica aqui:

seq 5 | awk '{print "Hello World"}'


1

Tente este:

echo $(for i in $(seq 1 100); do printf "-"; done)

Criará (cem traços):


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.