bir kalıptan sonra olmayan çizgiler için grep
Belirli bir kalıbın peşinde olmayan bir dosyanın tüm satırlarını bulmaya çalışıyorum.
Bir süredir , komutların kopyalarda göründüğü history
GNU bash
(sürüm 4 ve 5) kullanımımla ilgili bir sorun yaşadım . Bunun, bende .bashrc
aşağıdaki satıra sahip olmamdan kaynaklandığını varsaydım :
PROMPT_COMMAND="history -a; history -n; $PROMPT_COMMAND"
I terminalinden çoklayıcılar kullanılarak (ediyorum yana screen
ve / veya tmux
) sözü edilen komut yukarıda birkaç nedenle kez (işletilirse echo $PROMPT_COMMAND
sonuçlarıhistory -a; history -n; history -a; history -n;
Bazı durumlarda (özellikle farklı bölmelerde / pencerelerde / çerçevelerde / arabelleklerde eşzamanlı olarak bir şeyler yaparken) girdiğim son komut, iki kez veya daha sık olarak bende saklandı ~/.bash_history
. Bu, aşağıdaki gibi girişlere yol açtı:
#1596110297
yadm list -a | xargs -t ls -l
yadm list -a | xargs -t ls -l
Söylemeye gerek yok, bu oldukça can sıkıcı. Sadece (umarım) düzeltme: bu history
-issue için bir düzeltme buldum (komutu olarak değiştirerek PROMPT_COMMAND="history -a; history -n
) ancak history
,.
Şimdi yinelenen girişlerden kurtulmak istiyorum.
Bu nedenle şu anda ile başlayan #
ve ondan sonraki bir satır dışındaki her şeyi işaretlemek için düzenli bir ifade bulmaya çalışıyorum . İlk fikrim grep -v
(seçimi tersine çevirmek) ve grep -A 1
(eşleşen modelden sonra ek olarak bir satır elde etmekti ). Fakat
grep -v "^#" -A 1 ~/.bash_history
umduğum sonucu vermedi.
Bu nedenle benim sorum: bunu kullanarak nasıl yapılacağı konusunda iyi bir fikri olan var grep
mı? Değilse: nasıl bu diğer araçlarla başarabileceğini ( sed
, awk
, ...)?
Yanıtlar
Anladığım kadarıyla grep -v "^#" -A 1
, bir hash işaretiyle başlamayan satırları ve her birinden sonra bir satır yazdırmak anlamına geliyor. Ama tersini, çizgiler yazdırmak istemiyorum do sonra karma işareti ile başlar ve bir satır?
Bir test dosyası verildiğinde:
#123
echo this
echo this
#456
echo that
echo that
echo that
#789
echo third
grep -A1 ^# history.txt |grep -vxFe --
baskılar:
#123
echo this
#456
echo that
#789
echo third
İkincisi grep
, grup ayırıcı grep -A
baskılardan kurtulmaktır .
Alternatif olarak uniq history.txt
, her ardışık özdeş satır kümesinden yalnızca birini yazdırmak için çalışmalıdır.
Raku kullanarak (née Perl6)
Bu, birkaç komut dosyası dilinde mevcut olan "flip-flop" operatörü için bir iş gibi görünüyor. Aşağıda Raku programlama dilini (daha önce Perl6 olarak biliniyordu) kullanan bir cevap bulunmaktadır. İlk önce daha kapsamlı bir test dosyası oluşturarak başlayın:
$ cat repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
B_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
D_yadm list -a | xargs -t ls -l
E_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
G_yadm list -a | xargs -t ls -l
H_yadm list -a | xargs -t ls -l
I_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
Şimdi Raku'nun fff
"sed benzeri" davranışı uygulayan flip-flop operatörünü kullanan bir tek astarlı . İlk normal ifadenin ^^
değişmez bir "#" karakteri gördüğü (satırın başında) satırlar için yakalama AÇIK hale gelir . AÇIK olduğunda, yakalama ilk normal ifadeyi yok sayar ve ikinci normal ifadeye göre değerlendirir ve ^^
"#" karakteri eksik olan satırlarla eşleşme bulduğunda KAPALI duruma geçer . <-[#]>
Negatif bir "Numaralandırılmış Karakter Sınıfı" ve Raku dilinin gerçek bir özelliği olan 'negatif' normal ifade aşağıdaki kodda kullanılarak gerçeklenmiştir :
$ raku -ne '.put if /^^ "#" / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
Aslında, ilk normal ifade ( fff
ek operatörünün solunda ) <+[#]>
, daha paralel bir yapı için pozitif bir "Numaralandırılmış Karakter Sınıfı" olan kullanılarak yazılabilir :
$ raku -ne '.put if /^^ <+[#]> / fff /^^ <-[#]> /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
Ayrıca, bana göre bir satır başlangıcı "#" ve ardından bir veya daha fazla rakam için veya ona karşı bir eşleşme talep ederek normal ifadenizi iyileştirebilirsiniz, yani <digit>+
aşağıya bakın:
$ raku -ne '.put if /^^ <+[#]> <digit>+ / fff /^^ <-[#]> <-digit>+ /;' repeated_log.txt
#1596110297_1
A_yadm list -a | xargs -t ls -l
#1596110297_2
C_yadm list -a | xargs -t ls -l
#1596110297_3
F_yadm list -a | xargs -t ls -l
#1596110297_4
#1596110297_5
[Yukarıdaki kodun tümü, B, D, E, G, H ve I ile başlayan yinelenen satırları kaldırır. Fark ettiğim tek tuhaflık, çıktınızda "# 1596110297" gibi iki ardışık hedef satırının görünmesi, ancak net değil girdi dosyanız böyle ardışık satırlar içerecekse bana].