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.