Yanıtlar:
Bundan başka bir araç grep
gitmek için yoludur.
Perl kullanarak, örneğin, komut olacaktır:
perl -ne 'print if /pattern1/ xor /pattern2/'
perl -ne
stdin'in her satırı üzerinde verilen komutu çalıştırır; bu durumda eğer eşleşirse satırı basar, /pattern1/ xor /pattern2/
diğer bir deyişle bir deseni eşleştirir, diğerini seçmez (özel veya).
Bu, desen için her iki sırada da çalışır ve birden fazla çağrı yapılmasından daha iyi bir performansa sahip olmalı grep
ve daha az daktilo yazması gerekir.
Veya, daha kısa, awk ile:
awk 'xor(/pattern1/,/pattern2/)'
veya sahip olmayan awk sürümleri için xor
:
awk '/pattern1/+/pattern2/==1`
xor
Awk yalnızca GNU Awk'ta kullanılabilir mi?
/pattern1/+/pattern2/==1
İr ile değiştirebilirsiniz xor
.
\b
) kalıpların içine koyabilirsiniz , yani \bword\b
.
İle deneyin egrep
egrep 'pattern1|pattern2' file | grep -v -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
Direct invocation as either egrep or fgrep is deprecated
- tercih edingrep -E
-f
ve -e
seçeneklere sahip olduğundan bahsetmektedir . egrep
fgrep
grep
(yani destekler -F
, -E
, -e
, -f
POSIX gerektirir) içinde /usr/xpg4/bin
. Yardımcı programlar /bin
antika olanlardır.
İle grep
uygulamalara destek düzenli ifadeler perl benzeri (gibi o pcregrep
ya GNU veya ast-açık grep -P
), bir de bunu yapabiliyor grep
ile çağırma:
grep -P '^(?=.*pat1)(?!.*pat2)|^(?=.*pat2)(?!.*pat1)'
Yani çizgileri o maç bulmak pat1
değil pat2
, ya pat2
ama pat1
.
(?=...)
ve (?!...)
sırasıyla ileriye bakmak ve negatif görünüm öncesinde operatörleri vardır. Bu yüzden teknik olarak, yukarıdakiler ^
takip ettiği .*pat1
ve takip etmediği .*pat2
veya takip ettiği pat1
ve pat2
tersine çevrildiği takdirde konunun ( ) başlangıcını arar .
Bu, her iki deseni içeren satırlar için daha düşüktür ve iki kez aranır. Bunun yerine daha gelişmiş perl operatörleri kullanabilirsiniz:
grep -P '^(?=.*pat1|())(?(1)(?=.*pat2)|(?!.*pat2))'
(?(1)yespattern|nopattern)
eşleşiyor yespattern
ise 1
st yakalama grubu (boş ()
üzeri) eşleştirilmiş ve nopattern
aksi. O takdirde ()
kibrit, araçlarının pat1
biz bakmak eşleşmedi, böylece pat2
(öncesinde pozitif görünüm) ve biz bakmak değil pat2
aksi (negatif görünüm yeşil ışık).
Bununla birlikte sed
yazabilirsiniz:
sed -ne '/pat1/{/pat2/!p;d;}' -e '/pat2/p'
grep: the -P option only supports a single pattern
, en azından erişimime sahip olduğum her sistemde başarısız oluyor . Yine de ikinci çözümünüz için +1.
grep
. pcregrep
ve ast-açık grep bu sorunu yok. Ben birden yerini ettik -e
o GNU çalışmalıdır böylece, münavebe RE operatörüyle grep
de şimdiki gibi.
Boolean terimleriyle, olarak yazılabilecek A xor B'yi arıyorsunuz
(A ve B değil)
veya
(B ve A değil)
Sorunuzun, eşleşen satırlar gösterildiği sürece çıktının sırası ile ilgilenmediğinizden bahsetmediği göz önüne alındığında, A xor B'nin Boolean genişlemesi, grep'te oldukça basittir:
$ cat << EOF > foo
> a b
> a
> b
> c a
> c b
> b a
> b c
> EOF
$ grep -w 'a' foo | grep -vw 'b'; grep -w 'b' foo | grep -vw 'a';
a
c a
b
c b
b c
sort | uniq
.
Aşağıdaki örnek için:
# Patterns:
# apple
# pear
# Example line
line="a_apple_apple_pear_a"
Bu ile tamamen yapılabilir grep -E
, uniq
ve wc
.
# Grep for regex pattern, sort as unique, and count the number of lines
result=$(grep -oE 'apple|pear' <<< $line | sort -u | wc -l)
Eğer grep
Perl Düzenli ifadeler derlendi sonra yerine kadar boruya gerek son görüldüğü üzerine eşleşebilir uniq
:
# Grep for regex pattern and count the number of lines
result=$(grep -oP '(apple(?!.*apple)|pear(?!.*pear))' <<< $line | wc -l)
Sonuç çıktısı:
# Only one of the words exists if the result is < 2
((result > 0)) &&
if (($result < 2)); then
echo Only one word matched
else
echo Both words matched
fi
Bir astar:
(($(grep -oP '(apple(?!.*apple)|pear(?!.*pear))' <<< $line | wc -l) == 1)) && echo Only one word matched
Deseni kodlamak istemezseniz, değişken bir eleman grubuyla birleştirilmesi bir fonksiyonla otomatikleştirilebilir.
Bu, aynı zamanda, doğal olarak Bash'de borular veya ek işlemler içermeyen bir işlev olarak da yapılabilir, ancak daha fazla ilgili olacaktır ve muhtemelen sorunuzun kapsamı dışındadır.
Big apple\n
ve pear-shaped\n
çıktı her iki satırı da içermelidir. Çözümünüz 2 sayısını alacaktır; Uzun versiyon “Her iki kelimeyle eşleşiyor” şeklinde rapor eder (yanlış sorunun cevabıdır) ve kısa versiyon hiç bir şey söylemezdi. (3) Bir öneri: -o
burada kullanmak gerçekten kötü bir fikir, çünkü eşleşmeleri içeren satırları gizliyor, bu yüzden her iki kelimenin de aynı satırda göründüğünü göremiyorsunuz. … (Devam ediyor)
uniq
/ kullanmanız sort -u
bu soruya gerçekten yararlı bir cevap vermez. Ancak, yapsalar bile, yine de kötü bir cevap olurdu, çünkü soruyu cevaplamaya nasıl katkıda bulunduklarını açıklamıyorsunuz . ( İyi bir açıklama örneği için Stéphane Chazelas'ın cevabına bakınız .)
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) Eğer kelimelerden / kalıplardan biri bir satırda bir defadan fazla görünürse (diğeri görünmüyorsa)? Bu, bir kez görünen kelimeye eşdeğer mi, yoksa çoklu tekrarlamalar olarak mı sayılıyor?