Bir dizeyi bash olarak dizine ekle


15

Bir dizeye sh / bash dizinine göre nasıl başvurabilirim? Yani, temelde bölmek.

Bir dosya adının 5 karakterini soymaya çalışıyorum. Tüm adlar şu yapıya sahiptir: name_nr_code. 5 alfasayısal kod bitini kaldırmaya çalışıyorum. name_nr_her zaman 10 karakterdir.

Gibi bir şey var mı;

for i in * ; do mv "$i" "$i"[:10] ; done


5
bashBir shçözüm istiyorsanız neden etiket ?
Stéphane Chazelas

Yanıtlar:


16

Bu kadar basit.

(Deneme)

for i in * ; do mv -- "$i" "${i:0:5}" ; done

Voila.

Ve Gelişmiş Bash-Scripting Kılavuzu'ndan bir açıklama ( Bölüm 10. Değişkenleri Değiştirme ) , ( NOTEbu kılavuzdaki hataları vurgulamak için ek satır içi):

Substring Çıkarma

${string:position}

Dan alt dize ayıklar $stringde $position.

Eğer $stringparametre "*" veya "@", o zaman bu ekstreler konumsal parametreler başlayan $position.

${string:position:length}

Özler $lengthgelen alt dize karakterler $stringde $position.

NOTEparametre genişletmelerinde eksik tırnaklar! echorastgele veriler için kullanılmamalıdır.

stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                       # abcABC123ABCabc
echo ${stringZ:1}                       # bcABC123ABCabc
echo ${stringZ:7}                       # 23ABCabc 

echo ${stringZ:7:3}                     # 23A
                                        # Three characters of substring.


# Is it possible to index from the right end of the string?

echo ${stringZ:-4}                      # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . . 

echo ${stringZ:(-4)}                    # Cabc
echo ${stringZ: -4}                     # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.

Konum ve uzunluğu argümanlar yerine sayısal bir sabit olarak değil, bir değişken olarak, o "parametreli" temsil edilebilir.


Eğer $stringparametre "*" veya "@" dir, o zaman bu ekstreler maksimum $lengthkonumsal parametreler başlayan $position.

echo ${*:2}          # Echoes second and following positional parameters.
echo ${@:2}          # Same as above.

echo ${*:2:3}        # Echoes three positional parameters, starting at second.

NOTE: expr substrbir GNU oluşumudur.

expr substr $string $position $length

Konumunda başlayan $lengthkarakterleri ayıklar .$string$position

stringZ=abcABC123ABCabc
#       123456789......
#       1-based indexing.

echo `expr substr $stringZ 1 2`           # ab
echo `expr substr $stringZ 4 3`           # ABC

NOTE: Bu echogereksizdir ve daha az güvenilir olmasını sağlar. Kullanın expr substr + "$string1" 1 2.

NOTE: exprçıkış 0 ise (veya -0, 00 ...) sıfır dışında bir çıkış durumuyla döner.


BTW. Kitap, resmi Ubuntu deposunda olduğu gibi abs-guide.


Bir hangi vasıta, ofset aslında var olduğu "pozisyon" biraz yanıltıcıdır söylemek ${var:1}değerini döndürmez var"1 pozisyon" dan, ama aslında 2. ila.
Kusalananda

Bu doğru, ama katılmadığınız sürece sıfırıncı bir pozisyon olabilir. Ki benim için bir sıkıntı değil.

9

POSIX'te sh,

  • "${var%?????}"bir $varson 5 arka karakter sıyrılmış (ya da $vareğer $var5'ten az karakter içeren)

  • "${var%"${var#??????????}"}"'nin ilk 10 karakteri $var.

  • "${var%_*}", ( -> ) öğesinin sonunda $vareşleşen _*en kısa dizeden çıkarılır .$varfoo_bar_bazfoo_bar
  • "${var%%_*}": en kısa eşleşme yerine aynı ama en uzun eşleşme ( foo_bar_baz-> foo).
  • almak istiyorsanız foo_bar_: "${var%"${var##*_}"}"( ${var##pattern}ile aynıdır, ${var%%pattern}ancak $varsonu yerine desen aramaya başlar ).

İle zsh:

  • $var[1,-6] ilk karakter için sondan 6'ya kadar (son 5 hariç hepsi).
  • $var[1,10] ilk 10 karakter için.

İle ksh, bashveya zsh:

  • "${var:0:10}": ilk 10 karakteri $var

İle bashya zsh:

  • "${var:0:-5}": Hariç tümü son 5 karakter (bir hata verir ve eğer senaryoyu çıkar $varzaman da, set ama 5'ten az karakter içeriyor $varile ayarlı değil zsh).

Bourne shuyumluluğuna ihtiyacınız varsa , güvenilir bir şekilde yapmak çok zordur. Sonucun yeni satır karakterleriyle bitmeyeceğini garanti ediyorsanız şunları yapabilirsiniz:

first_10=`expr " $var" : ' \(.{1,10\}\)'` # beware the exit status
                                          # may be non-zero if the
                                          # result is 0 or 0000000000

all_but_last_5=`expr " $var" : ' \(.*\).\{5\}'`

Ayrıca $var(sistemler arasında değişiklik gösterme) uzunluğu konusunda da bir sınırınız olacaktır .

Tüm bu çözümlerde, $vargeçerli karakterlerin bir parçasını oluşturamayan baytlar içeriyorsa, YMMV.


benim, gerçekten bu diş telleri için çirkin bir sözdizimi buldular.
kedi

2

shile (bildiğim kadarıyla gördüğünüz gibi) bir dize dışına alt dize alma yolunda yerleşik, ancak bir sağlamaz bashyapmanız olabilir

${i:0:10}

Bu size değişkenin değerinin ilk on karakterini verecektir i.

Genel biçim ${variable:offset:length}.


2

Çoğu kabuk, size yardımcı olabilecek bir tür parametre genişletmeyi destekler. Bash'da şunları kullanabilirsiniz:

substr=${string:4:5} # start at position 4, length 5.

İçinde dash, ofsetler desteklenmez, ancak önde gelen ve sondaki desenleri kullanabilirsiniz:

remove_first3=${string#???}
remove_last2=${string%??}

0

Öncelikle, fordosya adları için döngü kullanmayın .

Sonra böyle bir şey yardımcı olacaktır.

find ./ -type f | while read filename ;do
  newfilename=$(echo ${filename}|cut -c 1-10)
  mv ${filename} ${newfilename}
done

3
forDosya adlarıyla kullanmak neden kötü ?
choroba

Değişkenlerinizi belirtin ve printfdaha güvenli olmak için kullanın . ... ve read -r.
Kusalananda

3
OP'nin fordöngüsü belki eksik olanlar dışında iyiydi --. 4 satır kodunuzda en az 10 hata görebilirsiniz! dosya adlarını varsaymak gibi iyi bilinen kötü uygulamaların çoğu tek satır, yankı, eksik tırnak kullanın
Stéphane Chazelas
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.