Belirli bir sütunda belirli bir değere sahip satırlar nasıl grep yapılır?


9

Aşağıdaki gibi bir dosyam var

  200.000    1.353    0.086
  200.250    1.417    0.000
  200.500    1.359    0.091
  200.750    1.423    0.000
  201.000    1.365    0.093
  201.250    1.427    0.000
  201.500    1.373    0.093
  201.750    1.432    0.000
  202.000    1.383    0.091
  202.250    1.435    0.000
  202.500    1.392    0.087
  202.750    1.436    0.000
  203.000    1.402    0.081
  203.250    1.437    0.001
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

Sadece ilk sütunda ondalık .000 ve .500 olan satırları grep istiyorum, böylece çıktı bu şekilde olurdu

  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045  

2
Yeterince kolay görünüyor. Şimdiye kadar ne denedin? Kodunuzda ne gibi sorunlar yaşandı?
John1024

belki sizin için kolaydır ama grep '.000' ile denedim | grep '.005' ancak aynı değere sahip satırları diğer sütunlarda da sıralar
Mohsen El-Tahawy

3
Çok iyi. Sorunu kendiniz çözmek için dürüst bir girişimde bulunursanız, buradaki insanlar çok daha sempatiktir. Yorumunuzdaki kod bunu gösterir. Gelecekte, sorunuza böyle girişimler eklerseniz, muhtemelen daha hızlı yanıtlar alacaksınız.
John1024

Yanıtlar:


14

Grep kullanmıyorsunuz. Kullanın awk.

"your data" | awk '$1 ~ /\.[05]00/'

Çok iyi. Yazıldığı gibi, kod ondalık basamaktan sonra tam olarak üç basamak olmasına bağlıdır. Kullanımı daha sağlam olurdu awk '$1 ~ /\.[05]0*$/'.
John1024

1
@ John1024, aslında yazdığı gibi kod ondalık basamaktan sonra en az üç basamak olmasına bağlıdır . Girdide awk '$1 ~ /\.[05]00$/'değişken ondalık basamakların beklendiğini düşünmek için bir nedenim yoksa, kendime doğru eğilirdim (tam olarak üç basamak gerektirir).
Wildcard

2
@Wildcard Üçten fazla varsa, kod başarısız olabilir. Örneğin: echo 0.5001 | awk '$1 ~ /\.[05]00/'. Sadece tam olarak üç tane varsa güvenilir bir şekilde çalışır .
John1024

4
awk '$1 ~ /\.[50]00/ { print $0 }' myFile.txt

İlk sütun noktalara $1karşı eşleştirilecek kısmi eşleme /\.500|\.000/herhangi bir karakteri regex değil gerçek noktalar olmak için kaçar ~ve tüm satır yazdırmak$0


2
Eklemek için bir neden yok { print $0 }; Awk'un varsayılan eylemidir.
Joker

4

Sadece ilk sütunda ondalık .000 ve .500 olan satırları grep etmek istiyorum

Benim ilk düşümcem

grep '^ *[0-9][0-9][0-9]\.[50]00' filename

WSL kullanarak hızlı test

$ head testdata
              200.000    1.353    0.086
              200.250    1.417    0.000
              200.500    1.359    0.091
              200.750    1.423    0.000
              201.000    1.365    0.093
              201.250    1.427    0.000
              201.500    1.373    0.093
              201.750    1.432    0.000
              202.000    1.383    0.091
              202.250    1.435    0.000
$ grep '^ *[0-9][0-9][0-9]\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

Bunu ifade etmenin daha özlü yolları var.

$ grep -E '^ *[0-9]{3}\.[50]00' testdata
              200.000    1.353    0.086
              200.500    1.359    0.091
              201.000    1.365    0.093
              201.500    1.373    0.093
              202.000    1.383    0.091
              202.500    1.392    0.087
              203.000    1.402    0.081
              203.500    1.412    0.073
              204.000    1.423    0.065
              204.500    1.432    0.055
              205.000    1.441    0.045

İlk sütunda 3 basamaklı bir tamsayı parçası bulunmuyorsa

grep -E '^ *[0-9]+\.[05]00' testdata

Bazı durumlarda kullanmak gerekebilir [:digit:]yerine [0-9].

Ve bunun gibi.

man grep senin arkadaşın.


Bu kullanımı grepbenimkinden daha kolaydır. Bunu önce görseydim bir cevap göndermezdim. İyi iş!
Yokai

2

Kullanım durumunuza bağlı olarak, gerçek sayısal işlemleri de kullanabilirsiniz:

$ awk '{a = $1 % 1} a == 0 || a == 0.5' /tmp/foo
  200.000    1.353    0.086
  200.500    1.359    0.091
  201.000    1.365    0.093
  201.500    1.373    0.093
  202.000    1.383    0.091
  202.500    1.392    0.087
  203.000    1.402    0.081
  203.500    1.412    0.073
  204.000    1.423    0.065
  204.500    1.432    0.055
  205.000    1.441    0.045

BSD awk (OSX El Capitan, 20070501) ve GNU awk 4.1.4 ile test edilmiştir.


1
Uyarı çeyrek, vb.) bu Q'daki veriler için doğrudur, ancak başlatılmamışlara benzeyen diğer pek çok kişi için geçerli değildir.
dave_thompson_085

1
@ dave_thompson_085 gerçekten, ama gawk ile keyfi hassas aritmetik kullanabilirsiniz , kuşkusuz burada kullanmıyorum.
muru


2

İle awk:

$>awk '$1%.5==0' data.tsv 
200.000 1.353   0.086
200.500 1.359   0.091
201.000 1.365   0.093
201.500 1.373   0.093
202.000 1.383   0.091
202.500 1.392   0.087
203.000 1.402   0.081
203.500 1.412   0.073
204.000 1.423   0.065
204.500 1.432   0.055
205.000 1.441   0.045

İle mlr:

$>mlr --ifs tab --onidx filter '$1%.5==0' data.tsv 
200.000 1.353 0.086
200.500 1.359 0.091
201.000 1.365 0.093
201.500 1.373 0.093
202.000 1.383 0.091
202.500 1.392 0.087
203.000 1.402 0.081
203.500 1.412 0.073
204.000 1.423 0.065
204.500 1.432 0.055
205.000 1.441 0.045

2

Tamam, katkılarımı biraz geç ekleyerek, ama buna değer olduğunu düşünüyorum.

OP'ye uygunluk gereksinimi, ondalık değere sahip .000veya .500yalnızca ondalık değere sahip ilk sütundur . Önde gelen değerle ilgili olarak, aralık veya uzunluk olarak herhangi bir koşul yoktur. Sağlamlık için ilk sütunda önce hiçbir olmayan boş karakterler (veya artık birinci sütun var) ve orada olması dışında herhangi bir şey tarafından kontrol altında tutulması kabul edilmemelidir ilk sütunun içeriği bu olacak ondalık noktası, ., bir yerde.

OP kullanmak istiyor grep, bir eşleşme bulunduğunda tüm satırı yazdıracak, bu yüzden yapılacak tek şey, hepsine uyan deseni ve sadece gerekli olanı oluşturmak .

Sadelik kendisi ve hiçbir neden kullanmak sedveya awkolarak `grep bir dosya veya bir boru gibi kaynağını işleyebilir.

To grepdosya kullanımıgrep '^[^.]*\.[05]0\{2\}\s' the_file.txt

İçin grepbir boru, kullanımdanmy_command | grep '^[^.]*\.[05]0\{2\}\s'

Desen:, ^satırın başından başlar; [^.], ondalık olmayan karakterlerle eşleşir; *, mümkün olduğunca çok kez (hiçbiri dahil); \., ondalık ayırıcıyla eşleşir; [05], beş veya sıfırla eşleşir; 0\{2\}, 2 tane daha sıfırla eşleştir (açık ve kapalı küme ayracı öncesi ters eğik çizgiler kabuğun küme ayracı genişletme yapmaya çalışmasını engeller); \s, bir boşluk karakteriyle eşleştirin (sütunun sonu anlamına gelir - farklı bir kullanım durumunda kullanmak için sütun ayırıcı, genellikle bir virgül, noktalı virgül veya sekme ile değiştirin \t).

Bunun OP'nin istediği ile tam olarak eşleşeceğini unutmayın . Bu olacak değil maç .5000veya .0000tam takiben beş veya sıfır için desen görünüyor, çünkü, sayısal olarak eşdeğer olsa bile 2 daha sıfır Arkasında boşluk. Bu önemliyse, o zamana kadar diğer tüm cevaplar, test rakamından sonra 1'den büyük herhangi bir sıfırla eşleşecekleri için başarısız olurlar. Ve FloHimself tarafından cevap hariç, bunlar maç olacak şey ikinci sütunda başlar .000 ya .500, dahil .0003ve .500Tve FloHimself tek matematiksel denk olduğunu şey eşleşir .0ve.5, ne kadar sıfır olursa olsun. Sonuncusu, OP'nin belirttiği şeyle eşleşmese de, OP'nin zaten neye ihtiyaç duyduğuyla eşleşmesi muhtemeldir.

Son olarak, awkOP istenmesine rağmen gücü ve hızı isteniyorsa, grepkomut şu şekilde olur:

Bir dosya ile awk '$1 ~ /[^.]\.[05]0{2}$/' the_file.txt

Bir boru ile my_command | awk '$1 ~ /[^.]\.[05]0{2}$/'


1

Eğer grep kullanmakta ısrar ederseniz, bu sizin için işe yarayabilir. Sağladığınız ilk çıktıyı "file.txt" adlı bir metin dosyasına kaydettim ve sonra aşağıdaki komutu kullandım:

grep -e '2[^ ]*.000' file.txt & grep -e '2[^ ]*.500' file.txt

Hangi çıktı verir:

200.000    1.353    0.086
200.500    1.359    0.091
201.500    1.373    0.093
201.000    1.365    0.093
202.500    1.392    0.087
202.000    1.383    0.091
203.500    1.412    0.073
203.000    1.402    0.081
204.500    1.432    0.055
204.000    1.423    0.065
205.000    1.441    0.045

Zaten bir dosyadaysa çıktıyı bir metin dosyasına kaydetmeniz gerekmez. Ancak bir dosyaya kaydedilmemesi durumunda, verileri sağladığım grep komutuna da ekleyebilirsiniz ve en azından 2ilk sütunda artık ilk sayı olmayana kadar çalışmalıdır 2. Bu noktada, doğru yazdırmak için grep komutunu uygun karakterle güncellemeniz gerekir.

Bu ikili grepkomutla olan şey, ilki operatörün greparka planına gönderilmesidir &. Arka plana gönderilirken, bir sonraki grepkomut hemen ardından tekdüze bir çıktı verir. Tamamlamanız gereken görevin daha kolay yapılabilmesi için, başkalarının verdiği ve kullandığı awkveya hatta örneğini izlemeniz gerekir sed.

(Düzenle)

Bu kesinlikle grep'in ihtiyaçlarınız için en iyi veya en etkili kullanımı değildir, ancak biraz oynamanız ve grep için daha iyi bir his almanız için yeterli olmalıdır.


İlk işlem arka planda çalışır, ancak arka planda çalışmayı içeren , ancak biraz daha fazla daemonized . Ve girdinin girdiyle aynı sırada üretilmesi pek olası değildir; oldukça küçük örneğinizde bile, üçüncü satırda zaten yanlış gitti.
dave_thompson_085

Çıktının belirli bir sırada olması gerektiğini söylemiyor. Yalnızca ilk sütuna .500ve .000sütununa özgü olması gerekir . En azından en büyüğü gibi belirli bir sırada olması gerekiyorsa, bu kolayca yapılabilir. Ancak, yazdırılmakta olan ilk sütunların ilk 3 basamağı en azından en üst sıradadır. Bu 2[^ ]*.000ve 2[^ ]*.500. OP istedi ne oldukça uygun.
Yokai

Ayrıca sağladığım komutun verimlilik feragatnamesine ilişkin düzenlememe de dikkat edin.
Yokai
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.