bar
발생 후 첫 번째 발생의 줄 번호를 얻고 싶습니다 foo
.
이는 while
전체 파일에 대해 루프로 실행되어야 합니다. 이와 같이:
테스트 파일:
bar foo
xxx
xxx
xxx
bar
bar
xxx
bar
xxxx
xxx
xx
bar foo
xxx
xxx
bar foo
xxx
xxx
xxx
xxx
xxx
bar
bar
나는 다음을 찾아야 foo
하지만 첫 번째 것과 같은 줄에 있지 않습니다 foo
. 다음과 같은 것이 있으면 bar foo
찾고 싶습니다. 15번째 줄을 찾을 수 없습니다.
다음을 반환해야 합니다.
linenumbersfoo: 1 12 15
linenumbersbar: 5 15 21
내 코드:
linenumbersfoo=($(awk '/foo/ {print FNR}' test_file.sh))
length="${#linenumbersfoo[@]}"
while [[ $COUNTERR -lt length ]]; do
number=$((${linenumbersfoo["$COUNTERR"]}))
linenumbersbar[$COUNTERR]=$(awk '"$number"<=NR, /bar/ {print FNR;exit;}' test_file.sh)
let COUNTERR=COUNTERR+1
done
echo "${linenumbersfoo[@]}"
echo "${linenumbersbar[@]}"
나는 얻다:
linenumbersfoo: 1 12
linenumbersbar: 1 1
문제는 변수인 것 같습니다 . 예를 들어 대신 number
쓰면 작동합니다.5
$number
어떤 도움이라도 대단히 감사하겠습니다!
답변1
이 필드는 foo
이 필드와 함께 나타나므로 bar
매우 명확한 알고리즘을 만들 수 있습니다.
awk '/bar/ {A[NR]=0} /foo/ {A[NR]++} END {for(i in A) print i,A[i]}' file
1 1
5 0
6 0
8 0
12 1
15 1
21 0
두 번째 열을 이동하면 1 - true 및 0 - fals를 표시하는 행 번호를 얻을 수 있습니다.
1
5 1
6 0
8 0
12 0
15 1
21 1
0
해보자:
awk '/bar/ {A[NR]=0} /foo/ {A[NR]++} END {for(i in A) {if(A[l]) print i; l = i}}' file
5
15
21
승리! 첫 번째 줄을 표시하고 이를 원하는 형식(포맷된 출력)으로 변환합니다.
awk '
BEGIN {printf "linenumbersfoo:"}
/bar/ {A[NR]=0}
/foo/ {A[NR]++; printf FS NR}
END {printf "\nlinenumbersbar:"
for(i in A) {if(A[l]) printf FS i
l = i}
print ""
}
' file
linenumbersfoo: 1 12 15
linenumbersbar: 5 15 21
답변2
편집: 편집 내용과 일치하도록 개선 사항을 추가하십시오...
awk에 대한 제안:
BEGIN {
ffoo=0; ffoos=""; fbars="";
}
/foo/ {
ffoo=1; ffoos=ffoos" "NR;
}
/bar/ {
if ((match($0, "foo") == 0) && (ffoo!=0)) {
fbars=fbars" "NR;
ffoo=0;
}
}
END {
print "linenumbersfoo: "ffoos"\n";
print "linenumbersbar: "fbars"\n";
}
답변3
쉘 루프에서 이 작업을 수행하지 마십시오 awk
. 우리가 대신 수행합니다.
다음은 awk
스크립트 파일에 저장하고 호출할 수 있는 스크립트 입니다 awk -f script.awk filename
(질문의 가장 최근 편집 내용과 함께 작동하도록 수정됨).
BEGIN {
follows["foo"] = "bar"
follows["bar"] = "foo"
}
{
for (i = 1; i <= NF; ++i)
if (lookfor == "") {
if ($i in follows)
lookfor = follows[$i]
} else if ($i == lookfor) {
record[$i] = (record[$i] == "" ? "" : record[$i] OFS ) FNR
lookfor = follows[$i]
}
}
END {
for (i in record)
printf "%s:\t%s\n", i, record[i]
}
샘플 데이터에서 실행:
$ awk -f script.awk file
foo: 1 12 15
bar: 5 15 21
이 스크립트는 연관 목록을 설정합니다 follows
. 목록에는 foo
찾으면 찾아야 bar
하고, bar
찾으면 foo
다시 찾는 데 관심이 있음을 보여줍니다.
스크립트 awk
는 에서 문자열을 찾습니다 lookfor
. 처음에는 배열에서 키를 찾은 follows
다음 해당 배열을 사용하여 lookfor
다음에 찾을 문자열을 설정합니다. 찾고 있는 문자열을 찾을 때마다 record
해당 문자열의 연관 배열에 현재 줄 번호를 저장합니다.
마지막으로 record
수집된 라인 번호가 출력됩니다.
스타일리시한 라인
record[$i] = (record[$i] == "" ? "" : record[$i] OFS ) FNR
배열의 줄 번호 문자열 끝에 줄 번호를 추가합니다 record
. 문자열이 비어 있으면 현재 줄 번호로만 설정되지만, 이미 포함되어 있는 경우에는 기존 문자열과 줄 번호 사이에 쉼표가 삽입됩니다.
답변4
~을 위한부자:
for i in `awk '/foo/{print NR}' filename`; do sed -n "$i,/bar/{;=;p}" filename|sed "N;s/\n/ /g"| awk '/foo|bar/'; done|awk '/bar/{print $1}'|perl -pne "s/\n/ /g"| awk '{print "linenumbersfoo: "$0}'
산출:
linenumbersfoo: 1 12
~을 위한술집:
for i in `awk '/foo/{print NR}' filename`; do sed -n "$i,/bar/{;=;p}" o1|sed "N;s/\n/ /g"| awk '/foo|bar/'; done|awk '/bar/{print $1}'|perl -pne "s/\n/ /g"| awk '{print "linenumbersfoo: "$0}'
산출:
linenumbersbar: 5 18