Cygwin grep çıkışını yönlendiriyor veya yönlendiriyor


3

Cygwin'in izini düzenli bir cmd.exe içinde düzgün çalışmasını nasıl sağlayabilirim?

> grep -o 'ProductVersion\".*\".*\"' foo.txt | grep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
foo.txt:ProductVersion" Value="59.59.140.59"
grep: |: No such file or directory
grep: grep: No such file or directory
grep: [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+: No such file or directory

ve

> grep -o 'ProductVersion\".*\".*\"' foo.txt >> blah.txt
foo.txt:ProductVersion" Value="59.59.140.59"
grep: >>: No such file or directory
grep: blah.txt: No such file or directory

Memnuniyetle başkasının cevabını kabul eder, ancak kaçan teklifleri kullanmama komutumu değiştirmek sorunu çözdü. Teşekkürler, @barlop.

Özel araştırmamda değişiklik yapabildim

grep -o 'ProductVersion\".*\".*\"' foo.txt >> blah.txt

için

grep -o 'ProductVersion.*Value.*' foo.txt | grep -v Name >> blah.txt

Buna daha fazla geçici çözüm diyebilirim.


Bu doğru. Cmd.exe'de test etme, sonunda .bat'ta kullanılması
Thomas

Soruyu okudun mu? Bu Cygwin grep ve grep'ten çıktı örnekleri gösterdim.
Thomas

Hmmm doğru .... üzgünüm ..
Diogo

1
Bu, kaçan tırnakların ve soruna neden olan borunun bir karışımıdır, ancak nedenini bilmiyorum. İşe yaramayan bir örnek alırsam ve () borudan önceki bütün parçaya koyarsam, Çalış ama yapmıyor. Ama orada kaçış tırnak yoksa yapar.
barlop

1
stackoverflow.com/questions/2737107/piping-findstrs-output aynı sorunu gösterir. Grep'i bir .batta sarmak işe yarayacak gibi görünüyor. findstr, "" kaçış için de destekler ".
Thomas

Yanıtlar:


1

Cygwin's Grep için

Çözüm, ASCII değerini Bash cinsinden belirtebilmenizdir. " 22'de onaltılıktır.

İki nokta: İlk tırnak etrafındaki tek tırnak işaretlerini kaldırmanız gerekir, böylece $'\x22' değişmez olarak değil, özel olarak yorumlanır.

Ve ifadenin ikinci kısmı için sadece kullanamazsınız -o, olmak zorunda -oE.

Çünkü + parçası ERE, Ve olmadan -E, bu sadece BRE. Düşünüyor + değişmez.

Kanıt + kelimenin tam anlamıyla orada .. 55.55.55.55 eşleşmiyor ama bu olacak:

$ echo 3+.3+.3+.3+ | grep -o [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
3+.3+.3+.3+

Demek işte aldığın hat ama ayarladın.

Bash'in tırnak kullanmak yerine ASCII kodlarını genişletme özelliğini kullanma. Tırnakları ilk bölümden çıkarma ve ekleme -E ikinci bölüm için:

$ grep -o ProductVersion$'\x22'.*$'\x22'.*$'\x22' foo.txt | grep -oE [0-9]+\.[0
-9]+\.[0-9]+\.[0-9]+
59.59.140.59

KATMA

Değiştirirseniz [0-9]+ ile [0-9][0-9]* (Aynı olan), daha sonra grep kullanabilirsiniz -E.

Kullanabilirsiniz grep -P ve sonra kullanabilirsiniz \d için [0-9], ancak ikinci bölümün etrafında tırnak kullanmak zorundasınız. Veya \\d.

Aslında, işte orjinal probleminizi tamamen çözen harika bir çözüm .. Sadece problemli bit için bir alıntı yapmanız yeterli. (Bu arada, ikinci yarıdaki normal ifadeyi tekrarlama operatörünü kullanarak daha verimli hale getirebilirim, ancak bu konu üzerinde durduğum alıntılarla ilgili olduğumuz konu ile ilgili değil).

Bu çalışıyor. Tek tırnakların ilk bitten bırakılması ve kullanılması \" onları gerçek ifadeler yapmak için. Bu, tek bir alıntı yapılması gereken çifte alıntı hatalarını yuvarlar. (Windows NT'lerde eğer garip hata findstr Şüphesiz tek bir alıntı ile olmasa da, buna benzer bir şey vardır.)

grep -P ikinci bölümde kullanmamıza izin veriyor \d. İkinci yarıda normal ifadenin etrafına tırnak koyabiliriz. Ya da sadece etrafına tırnak koyabiliriz '\d\ veya yaptığım ve kullandığım kadar yapabiliriz \\d. ( \d Yalnız -şanslı ve alıntılanmamış, eşleşmeyecek çünkü Bash tarafından yorumlanır ve d ne zaman grep anladım.)

$ grep -o ProductVersion\".*\".*\" foo.txt | grep -oP \\d+\.[0-9]+\.[0-9\]+\.[0
-9]+
59.59.140.59

Şimdi teklif sorunuyla ilgilendiğimize göre, tekrarlama operatörü ile daha verimli hale getireceğim. Düzenli ifadesi 3{4} anlamına geliyor 3333. Düzenli ifadesi (fg){4} anlamına gelir fgfgfgfg.

$ grep -o ProductVersion\".*\".*\" foo.txt | grep -P '(\d.){4}'
ProductVersion" Value="59.59.140.59""

$ grep -o ProductVersion\".*\".*\" foo.txt | grep -P '('\\d.')'{4}
ProductVersion" Value="59.59.140.59""

$ grep -o ProductVersion'"'.*'"'.*'"' foo.txt | grep -P '('\\d.')'{4}
ProductVersion" Value="59.59.140.59""

Güzel, -E bayrağı için teşekkürler, çalışmasını sağlamak için bu versiyon regex'in çok daha çirkin bir lezzetini bıraktım.
Thomas

@Thomas bize çirkinliği gösterebilir misin? Hangi lezzet versiyonunu ve regex'i kullandın? Bu arada, daha iyi çivilemek için cevabı daha yeni güncelledim!
barlop

Çirkin sürümümde bahsettiğiniz [0-9] [0-9] * yapısını kullandım. ProductVersion grep'in yeni sürümleri benim için çalışmıyor. İlk 3'ü asla yürütmez (stdin'i bekler) ve sonuncusu akmaz. Şimdilik bununla devam ediyorum: c: \ eddynet \ projects & gt; grep -o 'ProductVersion. * Değer. *' Foo.txt | grep -v Adı | grep -oE [0-9] + \ [0-9] + \ [0-9] + \ [0-9] +>; blah.txt
Thomas

4

Bir Unix kabuğu kullanmıyorsunuz. Alıntı yapmak farklı.

Her nedense, Microsoft'un komut yorumlayıcısında tek tırnak işaretlerinin meta karakterleri olduğunu düşünüyorsunuz. Onlar değil. Özel bir önemi yoktur. Ayrıca, ters eğik çizgilerin Microsoft'un komut yorumcusu için de özel bir önemi yoktur. Onlar değil Meta karakterleri alıntılamak için kaçış karakteri. Bu şapka. Bu önemli olan çift tırnak işaretidir: onlar gibi meta karakterleri alıntılar <, >, ve | Komut yorumlayıcısının bunları tanımasını durdurmak için ve onlardan önceki herhangi bir ters eğik çizgi ilgisizdir.

Böylece komut satırınız, alıntılanan dizelerin üzerinde durduğu gibi, bu şekilde bozuluyor:

grep -o 'ProductVersion\ "* \" . * \ "'foo.txt | grep -o' [0-9] + \. [0-9] + \. [0-9] + \. [0-9] + '

Gördüğünüz gibi, bir boru hattı olduğunu düşündüğünüz şey aslında üçüncü çift tırnak işaretinizden başlayan ve satırın sonuna kadar uzanan yanlış sonlandırılmış bir alıntı dizedir. Aslında koşuyorsun sadece biri grep komutunu verin ve komut satırının sonunda bu alıntı dizinin tamamını verin. Sizin grep komut, tek tırnak işaretlerini biliyor ve hala çift tırnak işaretini içeren komut tercümanından aldığı komut kuyruğunu kırıyor (çünkü komut tercümanı bunları tanıyor, ancak kaldırmıyor), yedi kelimeye:

  1. -o
  2. ProductVersion\".*\".*\"
  3. foo.txt
  4. |
  5. grep
  6. -o
  7. [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+

Dolayısıyla bu dosyalar hakkında hata mesajları. Ama bu sizin grep komut en yapıyor. Komut yorumcusu kelimeler açısından işlemez ve Win32 programları tek bir iletiden geçirilir. komut kuyruğu , değil tartışma vektör Unix paradigmasında olduğu gibi. Unix (ve C dili) tarzında çalışmak istiyorsa, komut kuyruğunu kelimelere bölmek denilen programın görevidir. (Çalışma zamanı, Win32 için birçok C ve C ++ dili uygulamasının kitaplıklarını destekler, bunu sahnelerin arkasına bölerek yapar.

Nitekim birçok Win32 C ve C ++ programı yapan değil Cygwin kütüphanelerini kullanmak, tek tek tırnak işaretlerini özel olarak işlemez, komut yorumlayıcısının kendisinden daha fazla. Genelde komut kuyruğunu sadece iki kelimeye böldüler:

  1. -o
  2. 'ProductVersion\.*".*"' foo.txt | grep -o [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+

Önceki Microsoft'un C / C ++ derleyicisi ile derlenmiş bir program ne yapardı , Örneğin. İronik olarak, bu tür C / C ++ programları, komut yorumlayıcısı olmasa bile, alıntı yapılan dizelerdeki ters eğik çizgileri tanıyacaktır. Bu nedenle, komut kuyruklarının, iki alıntı dizesi yerine yanlış bir şekilde sonlandırılmış büyük bir kordon dizisi ile böyle göründüğünü düşünüyorlar:

 -o 'ProductVersion\ ". * \". * \ "'foo.txt | grep -o' [0-9] + \. [0-9] + \. [0-9] + \. [0-9] + '

Evet, bu kabus yazan bir komut dosyasıdır. Esasen, yayınlamak istediğiniz argüman vektörünün nasıl alıntılanacağına karar vermek için çalıştırdığınız programın hangi kurallara uyduğunu bilmek zorundasınız. Cygwin'in bir sözleşmesi var. Win32 için ticari C ve C ++ derleyicileri ile derlenmiş C ve C ++ programlarının başkaları var. (1980'lerde ve 1990'larda, Borland, Watcom ve Microsoft, DOS için C / C ++ derleyicilerinde komut kuyruğu lexing konusunda anlaşamadılar ve bunun sonucunda programlar arasında ters eğik çizgi karakter işleme konusunda çok ince bir fark vardı. başka incelikle farklı şekillerde.

Sen biliyorsun grep komut bir Cygwin programıdır, bu nedenle (a) komut yorumlayıcısının bir komut satırına birleştirilen iki basit komut olarak doğru bir şekilde tanıyacağı ve sonra (b) grep komutu doğru bir şekilde Cygwin algoritmasını kullanarak kelimelere bölünecektir. İşte bir yol:

grep -o 'ProductVersion^".*\^".*\^"' foo.txt | grep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'

Sizi yanlış anlıyor olabilirim ama önerdiğiniz satırı denedim ve saf cmd.exe C: \ & gt; c: \ cygwin \ bin \ grep -o 'ProductVersion ^ ". * \ ^". * \ ^ " 'foo.txt | grep -oE' [0-9] + \. [0-9] + \. [0-9] + \. [0-9] + '(önlemek için tam yolu kullanmak zorunda kaldım. ben de sahip olan gnuwin32'i çalıştırıyorum). & lt; - ve eşleşmiyor. (grep -oE ile bile) .Sigwin kabuklarını yüklüyor ve çalıştırıyorsa eşleşmiyor. ilginç, (ilk satırında) cygwin'i yüklemeden bir cygwin programı çalıştırdığını mı düşünüyorsunuz? Sanırım öyleyse, bunu yapmak için çok yanlış bir yol.
barlop

Ayrıca, C ve C ++ 'dan başka bir dilde yazılmış, sahne arkasında bölünmeyen çok sayıda komut var mı? Aklında hangi dili (yaygın olarak yazıldığını) yazdınız? veya C ve C ++ uygulamalarının başka bir (azınlık) uygulaması mı?
barlop

Cevabınız hatalı olsa da + 1 verdim.
barlop

Odak noktanız hatalı. Anketör açıkça belirtildi iki defa bu xe kullanıyor cmd. Benim tarafımda hiçbir varsayım gerekli değildir. Sorgu yapan kişi ayrıca boru / yönlendirmenin işe alınmasını istedi; kullanılan normal ifadeleri değiştirmemekle ilgili değil. Bu nedenle, normal ifadelerden, ince havadan seçmiş olduğunuz verilerle uyuşmuyor. Buradaki odak nokta bir boru hattında ve yönlendirme ile çalışmak için gerçek komutları almak. Tanrı aşkına! Gerisi gelince: Şimdilik, bu sitelerin nasıl çalıştığını bilmelisiniz. Yorumlar StackOverflow soruları için değildir.
JdeBP

Bu uyumsuzluk kullandığınız kaçanlarla yaptığınız bir hatanın altında olsaydı bir sorun olabilirdi, ancak bu durumda olmasa da, uyumsuzluk benim yorumumda başıboş bir boşluk bıraktı, hata değil ikinci bölümde tam grep yolunu kullanarak. Bir yorumda "stackoverflow sorusu" nu ele almanın uygun olmadığını düşündüğünüze göre. Ayrıca, C / C ++ derleyicilerindeki "tail tail lexing" komutunu yazarken yazdığınız gibi "stackoverflow yanıtı" vermenin uygun olmadığını belirleyebilirsiniz. DOS". Sadece ne yazdığın hakkında bir soru soruyordum.
barlop
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.