Son satır eşleşmesini değiştir


2

Bir metindeki son satır eşleşmesini nasıl değiştiririm? Belli bir değeri değiştirmek istediğim bir yapılandırma dosyasına sahibim:

val1=0
val2=a
val3=?
val2=lol

Sadece grep değeri ile eşleşen son satırı değiştirmek istiyorum. sed -i 's/\(^val2=\)/\1yes/' iyi bir başlangıç, ancak ikisinin de val2 sadece son yerine satır.

Soruyu genel olarak Unix olarak etiketledim çünkü herhangi bir çözüme açığım: sed veya awk, Perl veya Ruby, Bash veya her neyse. Daha kısa bir çözüm ağız dolusu olandan daha seksidir.

Yanıtlar:


1

En iyi bulduğum şey şuydu:

tac config |while read LINE; do
  if [ "$DONE" != 1 ] && echo "$LINE" |grep '^\s*val2\s*=' >/dev/null; then
    echo "$LINE" |sed 's/^\(\s*val2\s*=\s*\)/\1yes/'
    DONE=1
  else
    echo "$LINE"
  fi
done |tac >config.new

Ancak bu, böyle yaygın bir görev için sevdiğim hızlı ve kirli boru hatları gibi hissetmiyor.


1

Bulunan komut dosyasına göre İşte :

sed -r ':0;/^val2=/!b;:1;$!N;/\n.*word/{h;s/\n[^\n]*$//p;g;s/^.*\n//};$!b 1;s/^(.*)(val2=)[^\n]*/\1\2yes/' file

Yanlış anlamış olabilirim, ancak bu satırları atlıyor gibi görünüyor. Koştuğum bir test durumunda son yapılandırma satırını kaybettim.
wilhelmtell

@ wilhelmtell: Sonuna kadar olan noktayı yeni olmayan bir satırla değiştirdim [^\n]. Tekrar dene.
Dennis Williamson

1

Genel fikir: girdiyi, ayrılmış \nval2=. Metni ilk satırsonuna kadar değiştirdiğimiz son yığın dışında her parçayı olduğu gibi yazdırın. İşte çoğu durumda işleyen nispeten basit bir çözüm.

gawk -v 'RS=\nval2=' -v ORS= \
  'RT {print $0 RT} !RT {sub(/[^\n]*/, "yes"); print $0}'

Bu, ilk satırın başlamadığını varsayar val2= ve en az bir maç olduğunu. Her iki hatayı düzeltmek senaryoyu belirgin şekilde karmaşıklaştırır:

gawk -v 'RS=\nval2=' -v ORS= \
  '!RT {if (NR==1) sub(/^val2=[^\n]*/, "val2=yes"); else sub(/[^\n]*/, "yes")}
   {print $0 RT}'

İşte aynı genel prensibi temel alan bir Perl çözümü, ancak tüm dosyayı bir kerede okuyor. Daha net buluyorum çünkü özel davalarla uğraşmak zorunda kalmıyor (boş dosya dışında).

perl -e 'undef $/;
         @chunks = split /(?=^val2=)/m, <>;
         $chunks[@chunks-1] =~ s/(?<=^val2=).*/yes/ if @chunks;
         print @chunks'

Perl'in genişletilmiş regexps'i ile tek bir regexp ikamesi kullanabiliriz. Sadece eşle ^val2= bu başka bir kişi tarafından takip edilmedi ^val2=:

perl -e 'undef $/; $_=<>; s/^val2=.*\n(?!.*\nval2=)/val2=yes\n/m; print'

Python'ın avantajlarından yararlanmaya çalıştım rsplit Son N alanlarını ayırabilir, ancak Perl çözümlerine göre daha fazla şifreli olmadan çalışamadığımda vazgeçtim.


Bunun işe yaradığını onaylamadım, ancak: harika bir cevap
Arjan
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.