J'ai une longue ligne que je veux insérer un espace tous les 4 caractères, sur une seule ligne isolée de texte solide pour faciliter la lecture, quel est le moyen le plus simple de le faire? De plus, je devrais pouvoir saisir la ligne d'un tuyau. par exemple.
echo "foobarbazblargblurg" | <some command here>
donne
foob arba zbla rgbl urg
Utilisez SED comme suit:
$ echo "foobarbazblargblurg" | sed 's/.\{4\}/& /g'
foob arba zbla rgbl urg
Vous pouvez utiliser l'exemple simple suivant:
$ echo "foobarbazblargblurg" | fold -w4 | paste -sd' ' -
foob arba zbla rgbl
Avec zsh
uniquement:
str=foobarbazblargblurg
set -o extendedglob
printf '%s\n' ${str//(#m)????/$MATCH }
Ou
printf '%s%s%s%s ' ${(s::)str}
avec ksh93
seul:
printf '%s\n' "${str//????/\0 }"
Avec n'importe quelle coquille POSIX uniquement (évitant également l'espace de fin si la longueur d'entrée est un multiple de 4):
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"
Maintenant, c'est pour caractères. Si vous vouliez le faire sur des grappes graphèmes (par exemple, briser Stéphane
, écrit comme $'Ste\u0301phane'
, comme Stép hane
et pas Ste phan e
), avec zsh
:
set -o rematchpcre
str=$'Ste\u301phane' out=
while [[ $str =~ '(\X{4})(.+)' ]] {
out+="$match[1] " str=$match[2]
}
out+=$str
printf '%s\n' $out
Avec KSH93, vous pourriez également casser la largeur d'affichage, ce qui fonctionnerait pour ça Stéphane
ci-dessus, mais pourrait également aider lorsque d'autres types de caractères zéro-largeur ou de double largeur sont impliqués:
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"
En bash seulement, pas de commandes externes:
str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
ou en tant que version de tuyau d'une ligne:
echo foobarbazblargblurg |
{ IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }
La façon dont cela fonctionne est de convertir chaque caractère de la chaîne à un " (.) " Pour une comparaison regex et capture avec =~
, Alors que la sortie des expressions capturées à partir BASH_REMATCH[]
Tableau, regroupées selon les besoins. Leading/arrière/espaces intermédiaires sont conservés, enlever les guillemets autour "${BASH_REMATCH[@]:1}"
De les omettre.
Ici, il est enveloppé dans une fonction, celle-ci traitera ses arguments ou lire stdin s'il n'y a pas d'arguments:
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
Vous pouvez facilement paramétrer le compte pour ajuster la chaîne de format en conséquence.
Un espace arrière est ajouté, l'utilisation de deux printf
s au lieu d'un, si c'est un problème:
printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"
Les premiers printf
tirages (jusqu'à) les 4 premiers caractères, la deuxième condition imprime tout le reste (le cas échéant) avec un espace qui conduit à séparer les groupes. Le test est de 5 éléments non 4 pour tenir compte de l'élément zeroth.
Remarques:
printf
'S%c
Pourrait être utilisé au lieu de %s
, %c
(Peut-être) rend l'objet plus claire, mais pas de caractères multi-octets. Si votre version de bash est capable, ce qui précède est tout caractère multi-octets.printf
réutilise sa chaîne de format jusqu'à ce qu'il court d'arguments, donc juste gobe 4 arguments à la fois, et gère les arguments de suivi (si aucun cas Edge nécessaire, contrairement à certains des autres réponses ici qui sont sans doute tort)BASH_REMATCH[0]
Est l'ensemble de la chaîne correspondante, de sorte que la sortie de départ à partir de l'index 1printf -v myvar ...
Au lieu de stocker à une variable myvar
(sous réserve de lecture en boucle habituelle/comportement sous-shell)printf "\n"
si nécessaireVous pouvez faire le travail ci-dessus dans zsh
si vous utilisez le tableau match[]
à la place de BASH_REMATCH[]
, Et soustraire 1 de tous les indices que zsh
ne garde pas un élément 0 avec le match.
Voici l'exemple en utilisant grep
et xargs
:
$ echo "foobarbazblargblurg" | grep -o .... | xargs
foob arba zbla rgbl
Je l'ai fait en utilisant python
D'abord, je lis le fichier alors je divise de 4 personnages et ajoute de l'espace
#!/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 ==> se compose du contenu que vous avez donné par exemple
sortir
foob arba zbla rgbl