Bir dizenin önündeki karakterler nasıl 'bırakılır' / silinir?


13

Ben manipüle etmek istiyorum bir dize var. Dize H08W2345678çıktı sadece böylece nasıl manipüle edebilecekti olduğunu W2345678?

Ben son 4 karakteri bırakmak istedim Benzer eğer H08W2345678alıyorum ki H08W234bunu nasıl?


1
Dizeleri manipüle etmenin birçok yolu vardır. Kullanmak için özel bir neden var mı sed?
don_crissti

@don_crissti Deneyim eksikliği dışında bir sebep yok. Herhangi bir alternatif açıktır ...
3kstc

@ don_crissti, hikaye: filtrelenmiş bir CSV dosyasından, parametrelerden birini alıp H08W2345678manipüle etmesi gereken bir satırdan alıyorum W2345678. E-posta gönderme işlemi cron ile yapılacaktır.
3kstc

@don_crissti awking. Ben bir dizi oluşturmak ve sonra dizi içindeki her öğeyi değiştirmek (hepsi farklı - yani Epoch zaman damgasını saniye olarak bir tarihe değiştirmek vb.)
3kstc

2
Sen awk ile böyle şeyler yapabilirsiniz:printf %s\\n "XX,H08W2345678,YY" | awk -F, '{print substr($2, 4); print substr($2, 1, length($2)-4)}'
don_crissti

Yanıtlar:


20

Sadece bash (veya ksh93sözdiziminin veya nereden geldiği zsh) kullanarak:

string="H08W2345678"

echo "${string:3}"
W2345678

echo "${string:0:-4}"
H08W234

Tel manipülasyonu hakkında daha fazla bilgi için Wooledge wiki'sine bakın .


Bu, bash 4.2 veya üstünü gerektirir. Bkz Bash Referans Kılavuzunun bu eski kopyasını Bölüm 3.5.3 '' Shell Parametre Genişleme '' ya burada piliçlerin cevabı eski kısıtlamayı görmek için ( “ uzunluk büyük bir sayı için değerlendirmek veya sıfıra eşit olmalıdır.”); … (Devam)
Scott

(Devamı) ... bkz (Bash Hackerlar Wiki) Bash değişiklikleri ya da (bölümün altına doğru kaydırın) Case Western Reserve Üniversitesi'nde Teknoloji Altyapı Hizmetleri kuruluşta bash haberleri “bash-4.2 eklenen” için arama ( ve ardından revizyonu görmek için "q" öğesine ilerleyin). …………  "${string:0:${#string}-4}" Uzunluğu $stringen az 4 olduğu sürece bash 4.1 sürümünde çalışır .
Scott

Not: Bu aynı zamanda abc-e, ilk üç karakteri bıraktığınızda bırakıldığınız gibi dizeleri de boğar -e(çünkü echo -eistediğiniz şeyi yapmaz).
Scott

8
$ echo "H08W2345678" | sed 's/^.\{3\}//'
W2345678

sed 's/^.\{3\}//'ilk üç karakteri bulan ^.\{3\}ve boşluk ile değiştirecek. Burada ^., dizenin başlangıcındaki herhangi bir karakterle eşleşir (dizenin ^başlangıcını gösterir) ve \{3\}önceki desenle tam olarak 3 kez eşleşir. Yani, ^.\{3\}ilk üç karakterle eşleşecek.

$ echo "H08W2345678" | sed 's/.\{4\}$//'
H08W234

Benzer şekilde, sed 's/.\{4\}$//'son dört karakteri boşlukla değiştirir ( $dizenin sonunu gösterir).


1
Açıklayabilir misiniz 's/^.\{3\}//'ve 's/.\{4\}$//'ben hala sed öğreniyorum gibi, çok teşekkürler
3kstc

@ 3kstc: Lütfen düzenlemeleri kontrol edin
heemayl

1
Sadece birkaç karakterler için, ben kullanırım ...yerine .\{3\}: okumak daha kolay (bana) beri sed -e 's/^...//' -e 's/....$//' birbiri ile ya da tek bir ifadede: sed -r 's/^...|....$//g'. Silinecek birkaç karakterden fazla olsaydı, /.\{17}\/ifadeyi yerine kullanırdım /.............../.
Johnny

Dize -eveya ise bu kötü davranacaktır -n. Birileri bu ilk veya son damla uyum istiyorsa Tabii ki, “Son 4 karakter bırak” anlamı, 4 karakterden daha kısa bir dize için tanımsız, ancak bir o kadar darbe olabilir, karakteri.
Scott

2

Her satırın, kesmek istediğiniz on bir karakterli (veya herhangi bir) dize olduğu bir dosyanız varsa, sedkullanılacak araçtır. Tek bir dizeyi değiştirmek için iyidir, ancak aşırıdır. Tek bir dize için, bash 4.2 veya daha üst bir sürüme erişiminiz varsa , Jason'ın cevabı muhtemelen en iyisidir. Ancak, ve sözdizimleri bash (well, bash, ksh93, mksh ve zsh) için benzersiz görünmektedir - Kabuk Komut Dili için Açık Grup Temel Spesifikasyonları'nda görmüyorum . Alt dize genişletmesini (çıkarma) desteklemeyen POSIX uyumlu bir kabukla sıkışıp kalırsanız,${parameter:offset}${parameter:offset:length}

$ printf "%s\n" "${string#???}"
W2345678

$ printf "%s\n" "${string%????}"
H08W234

ilk üç karakteri bıraktığınızda (ve istediğinizi yapmazsınız) gibi dizelere karşı korumak printfyerine kullanarak .echoabc-e-eecho -e

Ve eğer Bourne-ailesi bir kabuk kullanmıyorsanız (veya eski, POSIX öncesi bir sistem kullanıyorsanız), bunlar hala çalışmalıdır:

$ expr " $string" : ' ...\(.*\)'
W2345678

$ expr " $string" : ' \(.*\)....'
H08W234

Ekstra önde gelen uzay değerleri ile sorunları önlemektir $string gerçek olduğunu exproperatörleri (örneğin +,  /,  indexveya match) ya da seçenekleri (örneğin  --, --helpya da  --version).


@ Stéphane Chazelas: (1) Yaklaşık 40 yıl önce tanıdığım ve bir şekilde unutmayı başardığım bir tuzağı hatırlattığın için teşekkürler. (2) Bunu hep çözerdim X; ör expr "X$string" : 'X...\(.*\)'. IMO, bunu okumak ve anlamak daha kolay. Bununla ilgili bir problem veya boşluk tercih etmek için herhangi bir neden var mı? (3) Bugün expr + "$string" : '...\(.*\)'artık bunun işe yaradığını öğrendim . 40 yıl öncesinden hatırlamıyorum; güvenli olması için yeterince yaygın mı kullanılıyor? (4) Jasonwryan'ın cevabı hakkında bir not ve heemayl'ın cevabında nit-pick'u kaçırdınız.
Scott

AFAIK, bu expr +sadece GNU'dur (Solaris veya FreeBSD AFAICS üzerinde çalışmaz). Daha az olasılıkla bazı işte ben x'in yerine alanı kullanın expruygulanması ile daha boşlukla başlamak operatörleri olurdu xve daha az olası olmadığından ayrıca daha boşlukla başlar unsurları harmanlama olması x. Ama sonra expr " $a" "<" " $b"bazı uygulamalar sayılar gibi $a/ zaman $bgibi sayısal karşılaştırma yapmak sonuç olarak dize karşılaştırma için muhtemelen iyi bir seçim olmadığını anlıyorum . Belki expr "@@$a"...veya expr "x $a"daha güvenli olabilir.
Stéphane Chazelas

0

İle:

string="H08W2345678"

3 veya 4 karakter eşleştirmek basit görünüyor (çoğu kabuk için):

$ printf '%s\t%s\n' "${string#???}" "${string%????}"
W2345678      H08W234

Eski mermiler için (Bourne kabuğu gibi) kullanın:

$ string=H08W2345678

$ expr " ${string}" : " ...\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\)...." '
H08W234

Sayısal karakter sayısı gerekiyorsa, şunu kullanın:

$ expr " ${string}" : " .\{3\}\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\).\{4\}" '
H08W234

Tabii ki, bu normal ifade sed, awk ve bash 3.0+ ile de çalışır:

$ echo "$string" | sed 's/^.\{3\}//'
W2345678

$ echo "$string" | sed 's/.\{4\}$//'
H08W234

$ echo "$string" | awk '{sub(/^.{3}/,"")}1'
W2345678

$ echo "$string" | awk '{sub(/.{4}$/,"")}1'
H08W234

$ r='^.{3}(.*)$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
W2345678

$ r='^(.*).{4}$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
H08W234

-1

Bir dizenin önündeki karakterler nasıl 'bırakılır' / silinir?

Ben manipüle etmek istiyorum bir dize var. Dize H08W2345678 çıktı nasıl W2345678 böylece nasıl manipüle etmek?

echo "H08W2345678" | cut -c 4-

Bu sorunun sadece yarısını cevaplıyor.
Kusalananda

İnandığınız oyun haksız olduğuna inanıyorum. Bu yarım soruya cevap verir ben ben googled zaman vardı ilk karakterleri kaldırmak POSIX ve bu sayfayı arama sonuçlarında ortaya çıktı. Ayrıca, bu sayfa başlığı sorunun yalnızca yarısını kapsar. Sevdiğim çözümü bulduğumda geri döndüm ve katkıda bulundum - bence bu iş cut, bu sayfadaki her şeyden çok daha zarif.
aexl
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.