grep

grep

여러 파일이 있는 폴더가 있고 각 파일에서 1) 미리 지정된 단어 목록에서 항목이 포함된 모든 줄을 추출해야 합니다. 2) 줄 앞에 파일 이름을 추가합니다. 3) 추출된 줄을 두 개로 나눕니다. 문자열 사이의 일부 내용을 제거합니다.

추출해야 할 파일의 내용은 다음과 같습니다.

freq +fchi +t*CHI +s"m|v"
Fri Feb 24 10:24:17 2017
freq (08-Jan-2016) is conducting analyses on:
  ONLY speaker main tiers matching: *CHI;
    and those speakers' ONLY dependent tiers matching: %MOR;
****************************************
From file <sarah004.cha>
Speaker: *CHI:
  2 v|eye-3S
  1 v|get
  2 v|get&PAST
  1 v|go&PAST
  1 v|help
  2 v|ride
  3 v|see
  1 v|toe-3S
------------------------------
    8  Total number of different item types used
   13  Total number of items (tokens)
0.615  Type/Token ratio

내가 찾고 있는 단어 목록의 예는 see|know|look입니다(실제 목록은 훨씬 길어 약 25개 단어).

내가 원하는 최종 결과는 다음과 같습니다.

sarah004.cha    3    see
sarah006.cha    3    know
sarah010.cha    1    look
sarah010.cha    2    see
...

따라서 지정된 단어가 포함된 줄을 추출하는 것 외에도 숫자와 단어를 분리하고 v|도 제거하겠습니다.

디렉토리의 일부 파일에는 목록의 단어가 포함되어 있지 않을 수도 있고, 다른 파일에는 목록의 단어가 많이 포함될 수도 있습니다.

sed를 사용하여 이것이 수행될 수 있는지 확실하지 않습니다. 이것을 시작점으로 시도했지만(카운트가 있는 줄 추출) 실행이 완료되지 않습니다.

sed '/From file/{s/.*<\(.*\)>/\1/;h
}
/^  [0-9] v|/!d
s/.*= //;H;x' ./* | paste - - > sarahverbcounts.txt

여러 단계로 이 작업을 수행할 수 있지만 하나의 명령/스크립트로 수행할 수 있다고 확신하지만 방법은 모르겠습니다. 나는 Perl이 이것을 처리할 수 있다고 생각하지만 구문을 모릅니다(나는 찾은 Perl 예제를 사용해 보았지만 내 목적에 맞게 올바르게 변경하는 방법을 알 수 없었습니다). 단어 목록을 지정할 수 있도록 Python에서 이 작업을 시도해야 할 수도 있지만 Python에 디렉토리의 모든 파일을 하나씩 반복하여 모두 동일하게 작성하도록 지시하는 방법에 익숙하지 않습니다. 출력 파일(몇 가지 예를 보았지만 잘 이해가 되지 않습니다.) 어떤 제안이라도 감사하겠습니다. 가능하다면 솔루션이 어떻게 작동하는지에 대한 설명이 좋을 것입니다. 왜냐하면 저는 이 분야에 매우 익숙하지 않고 제가 제공한 유용한 답변을 항상 구문 분석할 수 없기 때문입니다.

답변1

검색하려는 단어 목록을 이름이 지정된 파일에 넣고 words.txt다음을 실행하십시오.

grep -Hf words.txt files.* | sed 's/:/ /;s/v|/ /'

답변2

이미지에 표시된 대로 다양한 방법으로 이 작업을 수행할 수 있습니다. 패턴은 목록 파일에 한 줄에 하나씩 저장됩니다.

참고: bash, perl 및 sed의 다양한 전략을 통해 패턴 파일을 나머지 데이터 파일(아마도 귀하의 파일 *cha)과 분리합니다. "sed"의 경우 패턴은 도트 파일(숨겨진 파일이라고도 함)에 저장되고 " .". awk에는 "FNR" 개념이 없으므로 "sed" 코드가 스키마 파일과 일반 데이터 파일을 구별하는 데 도움이 됩니다.

grep

grep -E -f ./.your_patterns_listfile ./* |
sed -e 's/://' -e 's/v|//'

진주

find . -maxdepth 1 -type f -name '*' -exec \
   perl -wMstrict -Mvars='*pat' -lne '
      BEGIN { ($pat) = @ARGV; }
      if ( $pat ne $ARGV ) {
         @pat = map { quotemeta } keys %pat unless @pat;
         next unless /^From file [<]/ .. /^--*/;
         my $cha;
         /^From file [<]([>]*)[>]/ and $cha = $1;
         for my $pat ( @pat ) {
            /^\s+ (\d+) \s+ v[|] ($pat) $/x and print(join("\t",$ARGV,$1,$2)),last
         }
      } else {
         $pat{$_}++;
      }
   ' ./your_patterns_listfile {} +

echo '.' >> ./.your_patterns_listfile
find . -maxdepth 1 -type f -name '*' -exec \
   sed -e '
      1{
         :pats
            N
         /\n\.$/!bpats
         s///;h;d
      }

      /^From file </!d
      $d;N
      /\n[ ]*\([1-9][0-9]*\)[ ]v|/{
         s//\n\1\t|/;s/$/|/
         G;s/\n/&&/;s/$/\n/
         /\n\n[1-9][0-9]*\t|\([^|]*\)|.*\n\1\n/{
            s/^From file <\([^>]*\)>\n\n\([1-9][0-9]*\)\t|\([^|]*\)|/\1\t\2\t\3\n&/
            P;s/\n\n.*//;D
         }
      }
      s/\n.*//;s/^/\n/;D
   ' ./.your_patterns_listfile {} +

불다

find . -type f -name '*' ! -name 'your_patterns_listfile' -exec \
   sh -c '
      shift $1
      flag=
      eval "`echo '\''readonly NL=qsq'\'' | tr '\''qs'\'' '\''\047\012'\''`"; # newline
      pats=$(< $1); shift
      cat "$@" |
      while IFS= read -r line
      do
         case $line in
            "From file <"* )
               cha=${line#*"<"}
               cha=${cha%">"}
               unset flag
               continue
               ;;

            *[0-9]*v\|* )
               pat=${line#*"|"}
               num=${line%%"v"*}
               num=${num//[ ]/}
               case $pats in
                  "$pat" | *"$NL$pat$NL"* | "$pat$NL"* | *"$NL$pat" )
                     ${flag+":"} printf "%s\t" "$cha" "$num" "$pat"
                     ${flag+":"} echo
                     ;;
               esac
               ;;

            '' | *[!-]* )
               :
               ;;

            * )
               flag=
               ;;
         esac
      done
   ' 2 1 ./your_patterns_listfile {} +

답변3

어쩌면 다음과 같은 것일 수도 있습니다.

egrep '^\s+[0-9]+\s+v\|([0-9a-zA-Z-]+)$' files* | sed -e 's/v|//g'

관련 정보