格雷普

格雷普

我有一个包含多个文件的文件夹,并且从每个文件中我需要 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

您可以通过多种方式完成此操作,如图所示。模式存储在列表文件中,每行 1 个。

注意:我们将模式文件与其余数据文件(大概是您的*cha注意:我们通过 bash、perl 和 sed 中的不同策略。对于“sed”,模式存储在点文件(也称为隐藏文件)中,并附加“.”。帮助“sed”代码区分模式文件和常规数据文件。这是 sed 的 WA,因为它没有 awk 中的“FNR”概念。

格雷普

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'

相关内容