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, printfsorun 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 printf4 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 %cyerine 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
zshDiziyi kullanmak match[]yerine yukarıdakileri çalıştırabilir BASH_REMATCH[]ve tüm dizinde zshbir 0 öğesi tutmadığından tüm dizinlerden 1 çıkarabilirsiniz .
sedilk önce kendimi tekmeleyebilirim.