grep? no.

Jun. 11th, 2003 01:18 pm
109: (Default)
[personal profile] 109
имеется много файлов, находимых по паттерну, в которых нужно найти строки, содержащие подстроку А и расположенные между строками, содержащими подстроки B и С. ответ должен обязательно содержать file name + line number, копия строки тоже желательна. какой тул поможет мне это сделать с минимальным геморроем?
(deleted comment)

(no subject)

Date: 2003-06-11 10:56 am (UTC)
From: [identity profile] 109.livejournal.com
идея была в том, чтобы не писать самому. сам-то я напишу, конечно...

ну вот давай, если интересно, посмотрим, сколько итераций потребуется для доведения твоего кода до полного удовлетворения user requirements.

во-первых, "расположенные между" вовсе не значит "next to each other". если B расположена на строке №1, А - на строке №3, а С - на строке №5, то это тоже должно быть found.

во-вторых, если все три подстроки расположены в одной строке в нужном порядке, то это тоже должно быть found.
(deleted comment)

(no subject)

Date: 2003-06-11 01:21 pm (UTC)
From: [identity profile] 109.livejournal.com
так я-то перла не знаю. я думал, вы быстренько исправите.

а тут у нас типа борьба трёх концепций развернулась: обойтись утилитами типа grep | xargs awk, написать на скриптовом языке типа перл, написать на нормальном языке.

(no subject)

Date: 2003-06-11 10:55 am (UTC)
From: [identity profile] duginov.livejournal.com
Ya dumal ty davno uzhe pljunul i napisal na C#. Delov-to na polchasa. System.Text.RegEx v zuby - i vpered...

(no subject)

Date: 2003-06-11 11:18 am (UTC)
From: [identity profile] 109.livejournal.com
есть такая концепция - использовать всякие разные тулы в работе. а не только notepad и компилятор. хотя бы потому что завтра задача может чуть измениться и надо будет писать вторую программу, а найденным мощным тулом её можно будет сделать и так. я предвижу предложение написать самому нечто более универсальное. так вот, мне кажется, что это кто-то уже написал до меня.

(no subject)

Date: 2003-06-11 11:23 am (UTC)
From: [identity profile] duginov.livejournal.com
Da ya s etim soglasen. Dumal prosto, chto tebe nado dovol'no srochno... Esli net - to, konechno prodolzhaj iskat' :)

(no subject)

Date: 2003-06-11 11:23 am (UTC)
From: [identity profile] caseq.livejournal.com
Во-во, у нас работал один такой, grep'ом пользоваться не умел, так каждый раз когда строчку надо найти было, специальную тулзу на C++ писал.

(no subject)

Date: 2003-06-11 11:37 am (UTC)
From: [identity profile] duginov.livejournal.com
Konstantin uzhe zayavil, chto GREP emu ne podhodit...

Variantov dva - iskat' drugoj tool (neopredelenno dolgo, ya ego eti voprosy uzhe vtoroj den' vizhu :) ili napisat' samomu po-bystromu.
S chem imenno ty ne soglasen?
Znaesh' tretij variant?

(no subject)

Date: 2003-06-11 11:46 am (UTC)
From: [identity profile] caseq.livejournal.com
Я не имел в виду что пользоваться в данном случае нужно именно grep'ом. Я имел в виду нежелание народа изучать полезные тулзы, которые заведомо всегда есть и не надо искать (find, xargs, grep, perl, awk, sed) и готовность тратить время на то, чтобы в каждом частном случае кропать специальную программу на не самом подходящем для text processing'а языке. А свой вариант я уже предложил ниже.

(no subject)

Date: 2003-06-11 12:07 pm (UTC)
From: [identity profile] msh.livejournal.com
Полчаса - это хорошо. Это наш вклад в борьбу с безработицей программистов

(no subject)

Date: 2003-06-11 01:24 pm (UTC)
From: [identity profile] 109.livejournal.com
да вот что-то уже сутки прошли, а работающего скрипта до сих пор нет. понятно, что есть объективные причины типа find кривой, и цигвин не стоит, но тем не менее...

(no subject)

Date: 2003-06-11 11:22 am (UTC)
From: [identity profile] caseq.livejournal.com

find -name pattern |
    xargs awk '/B/,/C/ { if ($0 ~ /A/) printf "%s(%d): %s\n",FILENAME,NR,$0; }'


(no subject)

Date: 2003-06-11 11:43 am (UTC)
From: [identity profile] 109.livejournal.com
так, уже что-то ближе к истине. только find не берёт файлы в поддиректориях, а grep -l добавляет в конец имени файла какое-то дурацкое двоеточие.

зы. а под sed слабо скрипт модифицировать? а то я sed уже поставил, а авк ещё нет :-)

(no subject)

Date: 2003-06-11 11:58 am (UTC)
From: [identity profile] caseq.livejournal.com
Если у тебя find не ходит в подкаталоги, у тебя, видать, какой-то левый неправильный find. unix'овый ходит. В принципе, ты можешь заменить его на dir /b /s | grep. Что же до awk'а, поставь уже себе cygnus и живи счастливо ;) sed'ом будет сложновато вставить имя файла и строчку.
From: [identity profile] msh.livejournal.com
C:\>find /?
Searches for a text string in a file or files.

FIND [/V] [/C] [/N] [/I] "string" [[drive:][path]filename[ ...]]

/V Displays all lines NOT containing the specified string.
/C Displays only the count of lines containing the string.
/N Displays line numbers with the displayed lines.
/I Ignores the case of characters when searching for the string.
"string" Specifies the text string to find.
[drive:][path]filename
Specifies a file or files to search.

If a path is not specified, FIND searches the text typed at the prompt
or piped from another command.
From: [identity profile] caseq.livejournal.com
Миша, ну зачем передергивать?! Ясно же, что первый шаг после установки NT, необходимый для превращения ее в систему, под которой удобно работать -- это не голую бабу на десктоп вешать, а поставить Cygwin и утащить его в путях вперед system32.
From: [identity profile] 109.livejournal.com
я поставил UnxUtils, они вроде без цыгвина работают. или там не всё нужное есть?

(no subject)

Date: 2003-06-11 12:37 pm (UTC)
From: [identity profile] 109.livejournal.com
C:\Dev\Thresher\Client>grep -l -d -o Debugger *.pas | xargs gawk "/except/,/end/ { if ($0 ~ /Debugger/) printf "d): s\n",FI
LENAME,NR,$0; }"

gawk: cmd. line:2: fatal: cannot open file `{' for reading (No such file or directory)

если внешние кавычки сделать одинарными, как ты написал, то он на них ругается, говорит, что illegal character.

(no subject)

Date: 2003-06-11 01:12 pm (UTC)
From: [identity profile] 109.livejournal.com
похоже, что дело портит xargs, потому что когда я ему скармливаю < filename, то всё работает.

(no subject)

Date: 2003-06-12 02:56 am (UTC)
From: [identity profile] caseq.livejournal.com
А :) Я все понял. Твоя ошибка в том, что ты думаешь что find должен искать строчки в файле. На самом деле, правильный find должен искать сами файлы, и выдавать в stdout их список. Поэтому он не взаимозаменяем с grep'ом для начала. Убедись что у тебя твои unix utild стоят в путях до винюковых каталогов, где лежит неправильный find. А, собственно, работа xargs состоит в том, чтобы список файлов из stdin положить в командную строчку.
Что до кавычек, то да, cmd не понимает апострофов (уроды). Можно написать и просто кавычки, но тогда могут быть осложнения с кавычками внутри. Надеюсь, ты их там сам победишь :)

(no subject)

Date: 2003-06-12 05:58 am (UTC)
From: [identity profile] 109.livejournal.com
huh? какой find? я же написал двумя постами выше, какой скрипт получился у меня из твоего. grep -l -d -o как раз и выдаёт в stdout список файлов.

кавычки я тоже победил (см. "с '< filename' всё работает")

спасибо anyway!

(no subject)

Date: 2003-06-11 11:30 am (UTC)
From: [identity profile] msh.livejournal.com

Ну я бы сделал чего-то типа этого

#!/usr/bin/perl
use strict;
for my $file (glob($ARGV[0])){
  open(IN,$file) or die $!;
  my ($between,$line);
  for my $string (){
    $line++;
    $between = 1 if ($string =~ /B/);
    $between = 0 if ($string =~ /C/);
    print "$file:$line $string" if ($between && $string =~ /A/);
  }
  close(IN);
}


но в вашей области я и не знаю чего делают в таких случаях

(no subject)

Date: 2003-06-11 11:56 am (UTC)
From: [identity profile] 109.livejournal.com
я спинным мозгом чувствую, что программа написана с максимально возможной ясностью, но всё равно не понимаю ни хера. вот, например, что такое my($between, $line);? нет, никогда в жизни не буду на перле писать.

и эта... если 'С' вообще в файле нет, оно же не должно выводить ничего? а вроде будет... или нет?

(no subject)

Date: 2003-06-11 12:06 pm (UTC)
From: [identity profile] msh.livejournal.com
my($between, $line) - это просто объявление переменных. Я такой нетипичный перл-программист, делаю use strict
замечание верное, конечно. Думаешь я этот скрипт вообще запускал? ;-)

Пусть будет так

#!/usr/bin/perl
use strict;
for my $file (glob($ARGV[0])){
  open(IN,$file) or die $!;
  my ($between,$line,$msg);
  for my $string (<IN>){
    $line++;
    $between = 1 if ($string =~ /B/);
    if ($string =~ /C/){
      print $msg;
      $msg='';
      $between=0;
    }
    $msg.="$file:$line $string" if ($between && $string =~ /A/);
  }
  close(IN);
}

(no subject)

Date: 2003-06-11 12:50 pm (UTC)
From: [identity profile] 109.livejournal.com
а тут у тебя получается, что вывод будет только если А и С в одной и той же строке. нет?

(no subject)

Date: 2003-06-11 01:49 pm (UTC)
From: [identity profile] msh.livejournal.com
Ты чего, в Индии уже?

Если A то добавится в $msg, а если C - то $msg напечатается и очистится

Re:

Date: 2003-06-11 02:25 pm (UTC)
From: [identity profile] 109.livejournal.com
в Индию 19-го.

да, я уже сообразил (после того, как убедился, что оно работает). ну заверши же теперь неоценимую помощь, скажи, как его для всех нужных мне файлов вызвать.

(no subject)

Date: 2003-06-11 01:54 pm (UTC)
From: [identity profile] 109.livejournal.com
вроде работает, непонятно почему :-)

как теперь его напустить на все файлы, удовлетворяющие маске, включая подкаталоги?

(no subject)

Date: 2003-06-11 02:49 pm (UTC)
From: [identity profile] msh.livejournal.com
Да я уж и не знаю, я бы find использовал, но если уж он не работает, пожет что-нибудь типа этого?

#!/usr/bin/perl
use strict;

traverse(@ARGV);

sub traverse($$){
  my ($path,$pattern)=@_;
  for my $file (glob("$path/*")){
    if (-d $file){
      traverse($file,$pattern);
    } elsif ($file =~ /$pattern/){
      process($file);
    }
  }
}

sub process($) {
  my $file = shift;
  open(IN,$file) or die $!;
  my ($between,$line,$msg);
  for my $string (<IN>){
    $line++;
    $between = 1 if ($string =~ /B/);
    if ($string =~ /C/){
      print $msg;
      $msg='';
      $between=0;
    }
    $msg.="$file:$line $string" if ($between && $string =~ /A/);
  }
  close(IN);
}

Profile

109: (Default)
109

March 2019

S M T W T F S
     12
3456789
101112131415 16
17181920212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags