여러 파일이 있는 폴더가 있고 각 파일에서 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'