Como insiro um espaço a cada quatro caracteres em uma linha longa?

27

Eu tenho uma longa linha que eu quero inserir um espaço a cada 4 caracteres, em uma única linha solitária de texto sólido para facilitar a leitura, qual é a maneira mais simples de fazer isso? Eu também deveria poder inserir a linha de um cano. por exemplo,

echo "foobarbazblargblurg" | <some command here>

foob arba zbla rgbl urg
    
por xenoterracide 17.01.2011 / 15:18

7 respostas

48

Use o sed da seguinte forma:

$ echo "foobarbazblargblurg" | sed 's/.\{4\}/& /g'
foob arba zbla rgbl urg
    
por 17.01.2011 / 15:26
15

Você pode usar o seguinte exemplo simples:

$ echo "foobarbazblargblurg" | fold -w4 | paste -sd' ' -
foob arba zbla rgbl
    
por 07.02.2015 / 16:49
2

Vou responder inserindo apenas espaços conforme necessário, para que um espaço apareça pelo menos a cada 4 caracteres em uma linha; Não tenho certeza de que maneira você quer lidar com este caso. Por exemplo, dada a entrada "aa bbccdd", você obteria a saída "aa bbcc dd" em vez de "aa b bccd d".

Estou usando o Perl para lookahead, mas não estou muito familiarizado com o Perl em geral, portanto, pode haver ajustes necessários:

$ echo "foobarbazblargblurg" | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
foob arba zbla rgbl urg

$ echo 'aa bbccdd' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
aa bbcc dd
# not 'aa b bccd d'!

$ echo 'some input' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
some inpu t
# not 'some  inp ut'!

$ echo $'aabb\nc cddee' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g' | 
> while read; do echo "${REPLY}x"; done
aabbx
c cdde ex
# no spaces added at the end of the first line (while loop to add to the end of
# the line and show this)
    
por 18.01.2011 / 07:23
2

Aqui está o exemplo usando grep e xargs :

$ echo "foobarbazblargblurg" | grep -o .... | xargs
foob arba zbla rgbl
    
por 05.05.2017 / 17:16
2

Apenas no bash, sem comandos externos:

str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"

ou como uma versão de tubo de uma linha:

echo foobarbazblargblurg | 
  { IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
    printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }

A maneira como isso funciona é converter cada caractere da string em um "(.)" para correspondência de regex e captura com =~ , em seguida, apenas exibe as expressões capturadas de BASH_REMATCH[] array, agrupadas conforme necessário. Os espaços iniciais / finais / intermediários são preservados, remova as aspas em torno de "${BASH_REMATCH[@]:1}" para omití-las.

Aqui está empacotado em uma função, esta processará seus argumentos ou lerá stdin se não houver argumentos:

function fmt4() {
  while IFS= read -r str; do
    [[ $str =~ ${str//?/(.)} ]]
    printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
  done < <( (( $# )) && printf '%s\n' "$@" || printf '%s\n' $(< /dev/stdin) )
}

$ echo foobarbazblargblurg | fmt4
foob arba zbla rgbl urg 

Você pode facilmente parametrizar a contagem para ajustar a string de formato de acordo.

É adicionado um espaço à direita, use dois printf s em vez de um, se isso for um problema:

printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"

O primeiro printf imprime (até) os primeiros 4 caracteres, o segundo condicionalmente imprime todo o resto (se houver) com um espaço à esquerda para separar os grupos. O teste é para 5 elementos, e não 4, para o elemento zeroth.

Notas:

  • printf do %c do shell pode ser usado em vez de %s , %c (talvez) torna a intenção mais clara, mas não é um caractere de multibyte seguro. Se a sua versão do bash é capaz, o acima é todo o caráter multi-byte seguro.
  • shell printf reutiliza sua string de formato até ficar sem argumentos, por isso apenas devolve até 4 argumentos por vez e manipula os argumentos finais (portanto, nenhum caso de borda é necessário, diferente de outras respostas aqui que são indiscutivelmente errado)
  • BASH_REMATCH[0] é toda a string correspondida, portanto, apenas a saída a partir do índice 1
  • use printf -v myvar ... para armazenar em uma variável myvar (sujeito ao comportamento usual de loop de leitura / subshell)
  • adicione printf "\n" se necessário

Você pode fazer o trabalho acima em zsh se usar a matriz match[] em vez de BASH_REMATCH[] e subtrair 1 de todos os índices, pois zsh não mantém um elemento 0 com a correspondência inteira.

    
por 30.08.2018 / 13:12
2

Com zsh apenas:

str=foobarbazblargblurg

set -o extendedglob
printf '%s\n' ${str//(#m)????/$MATCH }

Ou

printf '%s%s%s%s ' ${(s::)str}

com ksh93 apenas:

printf '%s\n' "${str//????/
out=
while true; do
  case $str in
    (?????*)
      new_str=${str#????}
      out=$out${str%"$new_str"}' '
      str=$new_str
      ;;
    (*)
      out=$out$str
      break
  esac
done
printf '%s\n' "$out"
}"

Com qualquer shell POSIX somente (evitando também o espaço à direita se o tamanho da entrada for um múltiplo de 4):

set -o rematchpcre
str=$'Ste\u301phane' out=
while [[ $str =~ '(\X{4})(.+)' ]] {
  out+="$match[1] " str=$match[2]
}
out+=$str
printf '%s\n' $out

Agora, isso é para caracteres . Se você quisesse fazer isso em clusters de grapheme (por exemplo, para quebrar Stéphane , escrito como $'Ste\u0301phane' , como Stép hane e não Ste phan e ), com zsh :

str=$'Ste\u301phane' out=
while
  start=${ printf %L.4s. "$str"; }
  start=${start%.}
  [ "$start" != "$str" ]
do
  out+="$start " str=${str#"$start"}
done
out+=$str
printf '%s\n' "$out"

Com o ksh93, você também pode dividir a largura de exibição, o que funcionaria para o Stéphane acima, mas também pode ajudar quando outros tipos de caracteres de largura zero ou de largura dupla estiverem envolvidos:

str=foobarbazblargblurg

set -o extendedglob
printf '%s\n' ${str//(#m)????/$MATCH }
    
por 30.08.2018 / 14:03
0

Eu fiz isso usando python

Primeiro eu estou lendo o arquivo, então estou dividindo por 4 caracteres e adicionando espaço

#!/usr/bin/python
import re
b=re.compile(r'[a-z]{4}')

p=open('/root/l.txt','r')
i=p.readlines()
for j in i:
    m=re.findall(b,j)
print " " .join (m) + "  "

/root/l.txt == > Consiste no conteúdo que você deu no exemplo

saída

foob arba zbla rgbl
    
por 22.01.2018 / 16:22