Sadece bash'da harici komut yok:
str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
veya tek hatlı boru versiyonu:
echo foobarbazblargblurg |
{ IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }
Bunun işleyişi, dizgenin her karakterini regex eşleşmesi ve yakalama için bir "(.)" Biçimine dönüştürmek ve =~
ardından BASH_REMATCH[]
dizilimden yakalanan ifadeleri gerektiği gibi gruplandırmaktır. Lider / iz / ara alanlar korunur, "${BASH_REMATCH[@]:1}"
atlamak için etrafındaki tırnak işaretlerini kaldırın .
Burada bir fonksiyona sarılır, bu herhangi bir argüman yoksa, argümanlarını işler veya stdin'i okur:
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
Format dizesini uygun şekilde ayarlamak için sayımı kolayca parametreleyebilirsiniz.
Takip eden bir boşluk eklenirse, printf
sorun olursa bir tane yerine iki saniye kullanın:
printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"
İlki ilk printf
4 karakteri (en fazla) basar, ikincisi koşullu olarak tüm diğerlerini (varsa) grupları ayırmak için başlarında boşluk bırakarak yazdırır. Test, sıfırıncı elementi hesaba katması için 4 değil 5 element içindir.
Notlar:
- Shell'in
printf
'ın %c
yerine kullanılabilir %s
, %c
(belki) niyet net yapar, ancak multi-byte karakter güvenli değil. Bash sürümünüzün yetenekli olması durumunda, yukarıdakilerin hepsi çok baytlık karakter güvenlidir.
- kabuk
printf
, biçim dizgisini argümanlar tükenene kadar yeniden kullanır, bu nedenle bir seferde 4 argüman toparlar ve izleyen argümanları ele alır (bu nedenle, tartışmasız yanlış olan diğer cevapların aksine, kenar davaları gerekmez)
BASH_REMATCH[0]
tüm eşleşen dize, bu nedenle yalnızca dizin 1'den başlayan çıktı
- kullanmak
printf -v myvar ...
bir değişkene mağazaya yerine myvar
(her zamanki salt döngü / altkabuk davranışına bağlı)
printf "\n"
gerekirse ekle
zsh
Diziyi kullanmak match[]
yerine yukarıdakileri çalıştırabilir BASH_REMATCH[]
ve tüm dizinde zsh
bir 0 öğesi tutmadığından tüm dizinlerden 1 çıkarabilirsiniz .
sed
ilk önce kendimi tekmeleyebilirim.