2016-03-19 14 views
1

Bir dizinde, farklı dosyalara sahip çok sayıda alt alt dizin vardır. Dize manipülasyonu sadece bir dosya türünde (ör. * .c) yürütülür.Tüm alt dizinlerdeki dosyaların bir alt kümesindeki dizelerin bash özyinelemeli yürütmesi

[text][string before specific underscore]_[string after specific underscore]_[string rest][text] 
  • [metin] [a-z], [A-Z], [0-9], _ ya da alan olabilir:

    I manipüle etmek istiyorum dize, aşağıdaki yapıya sahiptir.

  • [belirli alt çizgiden önceki dize] [a-z], [A-Z], [0-9] olabilir.
  • [belirli alt çizgi sonra] bilinir. 'MOVE' olduğunu varsayalım.
  • [string rest] [a-z], [A-Z], [0-9] veya _ olabilir.

    [text][string after specific underscore]_[string before specific underscore]_[string rest][text] 
    

    Örnek bir c dosyasının:

    h_a1Ha MOVE_Ab1_rest  h _4Aihi 
    bl_aa abc123ABC_MOVE_rest bl_ub 
    blu_b abcABC_MOVE_rest bla_a 
    foo _o Abc_MOVE_rest  tes _t 
    

    ben değiştirmek istiyorum

Amacım iki dizeleri sol ve sağ birinci alt çizgi ile değiştirmektir İlk alt çizgi öncesi ifadeye sahip MOVE:

h_a1Ha MOVE_Ab1_rest  h _4Aihi 
bl_aa MOVE_abc123ABC_rest bl_ub 
blu_b MOVE_abcABC_rest bla_a 
foo _o MOVE_Abc_rest  tes _t 

tüm ifadeler ilk alt çizgi öncesinde bilinen bu çalıştığında:

find . -name "*.c" -exec sed -i "s/abc123ABC_MOVE_/MOVE_abc123ABC_/g" '{}' \; 
find . -name "*.c" -exec sed -i "s/abcABC_MOVE/MOVE_abcABC/g" '{}' \; 
find . -name "*.c" -exec sed -i "s/Abc_MOVE_/MOVE_Abc_/g" '{}' \; 

Nasıl bu dize kullanımı yapabileceğiniz ilk altını önce açıkça dize yazmadan? Ben bu belirteç

_MOVE_ (_MOVE shall be also sufficient, I guess.) 

arar öncesi ve birinci alt çizgi sonra ne değiştiren bir normal ifade gerek.


Soru 2: Bir söz sorunu çözmek için nasıl bir fikri varsa

mükemmel olurdu.

h_a1Ha MOVE_Ab1_rest  h _4Aihi 
bl_aa MOVE_abc123ABC_rest bl_ub 
blu_b MOVE_abcABC_rest bla_a 
foo _o Abc_MOVE_rest  tes _t 

Teşekkür ve şerefe,

David

cevap

1

Ben belki bu bir deneyebilirsiniz, yukarıdaki iki cevaplar çok süslü olduğunu düşünüyorum, size sorunu çözmek için yeterli basit:

sed -r -e 's/([a-zA-Z0-9]+)_(MOVE)/\2_\1/g; s/(MOVE)_(Abc)/\2_\1/g' 
+0

Bu durumda, sizin için karakter. 1 sınıflarını tanımlamak daha güvenilir olmalıdır. – SLePort

+0

Mükemmel! ederiz ! Eğer –

+0

@Kenavoz aslında ben sadece en basit ifade yazabilirsiniz böylece RE acemi değilim, teşekkürler: P –

0

Kontrol Bu komut: Sonuç haline gelmesi belirli bir dize (örn Abc_) dışlamak olacaktır; (evet, mükemmel daha iyi) Daha da iyisi :

sed -r 's/([^_]*)_([^_]*)/1st: \1\n2nd: \2/' <<< 'foo_bar' 

size verir:

1st: foo 
2nd: bar 

Alt çizgilerden olmayan bir sıralamayı [^_]* ile eşleştirebilirsiniz. () parantezlerini kullanarak bunları ayrı ayrı yakalayabilir ve bunlara \1, \2 vb.

0

Bu deneyebilirsiniz:

$ sed '/[^ ]* Abc/!{/[^ ]* MOVE/! s/\([^ ]* \)\([^_]*\)_\([^_]*\)_\(.*\)/\1\3_\2_\4/} ' file 
haha MOVE_Ab1_rest  hihi 
blaa MOVE_abc123ABC_rest blub 
blub MOVE_abcABC_rest blaa 
fooo Abc_MOVE_rest  test 

İlk alt çizgi öncesinde dize MOVE veya Abc ile başlar dışında ilk çizgi çevreleyen dizeleri değiştirir.

Belki biraz daha okunabilir sen Genişletilmiş varsa Regex desteği (-r opsiyon):

sed -r '/[^ ]* Abc/!{/[^ ]* MOVE/! s/([^ ]*)([^_]*)_([^_]*)_(.*)/\1\3_\2_\4/}' file 

buradaki fikir alanlarda başa ve _ grupları yakalamak için. Olası ihmal edilmiş karakterlerle güncellenmesi gereken karakter sınıflarını kullanmaktan daha genel bir yaklaşımdır.

+0

O inşaat ama benim örnek olduğunu kesin değildi, üzgünüm! Hem açıklamayı hem de örneği değiştirdim. kod Satır artık çalışmıyor :(kod kolunuz adapte Could lütfen. Çok teşekkürler! –

+0

dördüncü satırında foo _o' 'bir yer yoktur, bu kasıtlı mı? – SLePort

+0

cevabım alanı bağlıdır ve As ilk bölümde ek boşluk varsa 'yakalama grupları için _', @ CLI cevabı daha uygun olmalıdır. – SLePort

İlgili konular