Eu tenho uma string de entrada como:
arg1.arg2.arg3.arg4.arg5
A saída que eu quero é:
arg5.arg4.arg3.arg2.arg1
Nem sempre são 5 argumentos, pode ser de 2 a 10.
Como posso fazer isso em um script bash?
shell
text-processing
Jens
fonte
fonte
Se você não se importa com um pouquinho de
python
:Exemplo:
s.split(".")
gera uma lista contendo.
substrings separados,[::-1]
inverte a lista e".".join()
une os componentes da lista invertida.
.fonte
Você pode fazer isso com uma única
sed
chamada:isso usa o buffer de espera para obter uma nova linha de frente no espaço do padrão e usa-o para fazer permutações até que a nova linha não seja mais seguida por nenhum ponto; nesse ponto, ele remove o ponto principal do espaço do padrão e substitui a nova linha por um ponto.
Com BRE e uma regex ligeiramente diferente:
Se a entrada consistir em mais de uma linha e você desejar reverter a ordem em cada linha:
fonte
Solução SED:
fonte
Com
zsh
:Para preservar elementos vazios:
s:.:
: dividir em.
Oa
: Matriz tipo, em sentido inverso um rray indice o rderj:.:
: junte-se.
.@
:"$@"
expansão do tipo quando estiver entre aspas duplas, para que a expansão não seja removida em branco.O
bash
equivalente POSIX (ou ) poderia ser algo como:(observe que
zsh
(emsh
emulação)yash
e algumaspdksh
conchas baseadas em não são POSIX nesse sentido, pois tratam$IFS
como um separador de campos em vez de delimitador de campos)Onde difere de algumas das outras soluções apresentadas aqui é que ele não trata o caractere de nova linha (e, no caso de
zsh
NUL) especialmente, ou seja,$'ab.cd\nef.gh'
seria revertido para$'gh.cd\nef.ab'
, não$'cd.ab\ngh.ef'
ou$'gh.ef.cd.ab'
.fonte
IFS="."; set -f; set -- $string$IFS; for i; do rev="$i$IFS$rev"; done; printf '%s\n' "${rev%$IFS}"
?for i; do
que ainda não é POSIX), mesmo que seja suportado por todos os shells POSIX que eu conheço. Só que essa solução é uma tradução direta dezsh
uma (dividida em matriz, matriz reversa, junção de elementos da matriz), mas usando operadores somente POSIX. (Eu mudeistring=$string$IFS; set -- $string
para para,set -- $string$IFS
pois parece funcionar de forma consistente entre conchas, obrigado).Vejo Rahul já postou uma solução nativa do bash (entre outras), que é uma versão mais curta da primeira que eu criei:
mas não consegui parar por aí e senti a necessidade de escrever uma solução centrada no bash recursiva:
fonte
Não encontrou uma
awk
resposta, então aqui está uma:fonte
Pure Bash, requer um período à direita na entrada:
Use
printf %s "$g"
se algum dos elementos pontilhados puder começar com um hífen.fonte