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