Nur in Bash, keine externen Befehle:
str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
oder als Einleitungsversion:
echo foobarbazblargblurg |
{ IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }
Dies funktioniert, indem jedes Zeichen der Zeichenfolge in ein "(.)" Konvertiert wird, um eine Übereinstimmung mit =~
dem regulären Ausdruck und eine Erfassung mit ihm zu erzielen. Anschließend werden nur die erfassten Ausdrücke aus dem BASH_REMATCH[]
Array ausgegeben , die nach Bedarf gruppiert sind. Führende / nachfolgende / Zwischenräume bleiben erhalten, entfernen Sie die Anführungszeichen, um "${BASH_REMATCH[@]:1}"
sie wegzulassen.
Hier ist es in eine Funktion eingeschlossen, diese verarbeitet ihre Argumente oder liest stdin, wenn es keine Argumente gibt:
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
Sie können die Anzahl einfach parametrisieren, um die Formatzeichenfolge entsprechend anzupassen.
Ein abschließendes Leerzeichen wird hinzugefügt. Verwenden Sie zwei printf
anstelle von einem, wenn dies ein Problem ist:
printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"
Der erste printf
druckt (bis zu) die ersten 4 Zeichen, der zweite druckt bedingt den gesamten Rest (falls vorhanden) mit einem führenden Leerzeichen, um die Gruppen zu trennen. Der Test ist für 5 Elemente, nicht für 4, um das nullte Element zu berücksichtigen.
Anmerkungen:
- Shell
printf
‚s %c
statt verwendet werden könnte %s
, %c
(vielleicht) macht die Absicht klarer, aber es ist nicht Mehrbytezeichensatz sicher. Wenn Ihre Version von bash in der Lage ist, sind alle oben genannten Zeichen mehrbyte-sicher.
- Shell verwendet die
printf
Formatzeichenfolge so lange, bis die Argumente aufgebraucht sind. Daher werden nur 4 Argumente gleichzeitig verschlungen und die nachfolgenden Argumente verarbeitet.
BASH_REMATCH[0]
ist die gesamte übereinstimmende Zeichenfolge, daher wird nur ab Index 1 ausgegeben
- Verwenden Sie
printf -v myvar ...
stattdessen, um in einer Variablen zu speichern myvar
(vorbehaltlich des üblichen Leseschleifen- / Subshell-Verhaltens).
printf "\n"
bei Bedarf hinzufügen
Sie können das oben beschriebene Ergebnis erzielen, indem zsh
Sie das Array match[]
anstelle von verwenden BASH_REMATCH[]
und 1 von allen Indizes subtrahieren, da zsh
kein 0-Element für die gesamte Übereinstimmung beibehalten wird.
sed
Ich fluchte , das war so nah an dem, was ich zuerst versucht hatte, dass ich mich selbst treten konnte.