awk를 실행할 때 파일의 문자열을 값으로 처리하는 방법은 무엇입니까?

awk를 실행할 때 파일의 문자열을 값으로 처리하는 방법은 무엇입니까?

나는문서일부 누락된 데이터 포인트에 대한 값이 있으며, 누락된 값은 로 표시됩니다 ****. 10보다 작은 값을 갖는 7개의 연속된 열이 있는 행을 선택해야 합니다. 내가 실행할 때스크립트****또한 연속 열에 해당 행을 제공합니다 .

**** 모든 것을 더 높은 값으로 바꾸면 쉽게 문제를 해결할 수 있습니다. 그러나 입력 파일을 변경하고 싶지 않습니다. 내 스크립트가 ****숫자(보다 큼 ) 로 처리하도록 뭔가를 하고 싶습니다 10 i.e. str=****=100. 어떻게 해야 하나요?

입력 예 consecutive7pointDown10.input-

2     3    4    5    6    7    8   0  12   14   23
2     3    4    12   6    7    8   0  1     2   23
**** **** **** **** **** **** **** 8 ****  **** 12

내 스크립트의 결과 consecutive7pointDown10.output-

2     3    4    5    6    7    8    0    12    14   23
**** **** **** **** **** **** ****  8   ****  ****  12

그러나 예상 출력

2     3    4    5    6    7    8    0    12  14   23

내 스크립트 consecutive7pointDown10는 다음과 같습니다 -

#!/bin/bash
########################################################################################################################
# This script results rows having at most 10°C in consecutive at most 7 points.
# input = scriptname.input
# output = scriptname.output
########################################################################################################################
input=`basename "$0"`.input
output=`basename "$0"`.output
awk '{
    for(i=4;i<=34-6;i++)
        {   
            if($i<=10 && $(i+1)<=10 && $(i+2)<=10 && $(i+3)<=10 && $(i+4)<=10 && $(i+5)<=10 && $(i+6)<=10)
            {
                print
                next
            }
        }
}' $input > $output

답변1

awk '/(\<[0-9]\s+){7}/{print}' input.txt

또는

sed -rn '/(\b[0-9]\s{1,}){7}/p' input.txt

일을 할 것입니다.

awk의 설명(sed의 논리는 동일함):

  • /(\<[0-9]\s+){7}/{print}- 패턴이 포함된 라인을 인쇄합니다.

  • \<- 단어 경계와 일치합니다. 즉, 오른쪽 문자가 "단어" 문자이고 왼쪽 문자가 "비단어" 문자인 경우 일치합니다.

  • [0-9]\s+0- 에 한 자리 숫자 9, 그 뒤에 하나 이상의 공백이 옵니다.
  • (\<[0-9]\s+){7}- \<[0-9]\s+패턴이 7번 반복되면 일치합니다.

입력하다

2     3    4    5    6    7    8   0  12   14   23
2     3    4    12   6    7    8   0  1     2   23
**** **** **** **** **** **** **** 8 ****  **** 12

산출

2     3    4    5    6    7    8   0  12   14   23

편집하다:

정밀도가 1인 부동 소수점 숫자(9.2, 8.1, 7.5 등)의 경우.

awk '/(\<[0-9]\.[0-9](\s+|$)){7}/{print}' input.txt

답변2

awk모든 조건이 충족되면 증가하거나 반대의 경우에는 재설정되는 플래그를 사용하면 연속된 7개의 열을 반복적으로 검사하는 것을 피할 수 있습니다 .

awk '{c=0; split($0,arr,/ +/);
    for(x in arr) if(arr[x]<10 && arr[x]>=0) {
        if(++c==7){ print $0; next } }else{c=0} }' infile

여기서 우리는awk의 분할 기능« split(string, array [, fieldsep [, seps ] ])» 라인( $0전체 라인을 나타냄) 을 awk하나 이상의 공백으로 구분된 명명된 배열로 분할합니다.arr

다음으로 배열 요소를 반복하고 해당 값이 10과 0 사이인지 확인한 다음 call이라는 플래그를 증가시키고 c, 7에 도달하면 줄을 인쇄합니다(7개의 연속 요소(열)가 조건을 충족함을 의미). 플래그는 0으로 설정됩니다.


또는 행을 배열로 분할하지 않고 동일한 방식으로 수행합니다.

awk '{c=0; for(i=1;i<=NF;i++) if($i<10 && $i>=0) {
    if(++c==7){ print $0; next } }else{c=0} }' infile

귀하의 경우 4열부터 끝까지 필터링하려면 다음과 같은 것이 필요합니다. NF로 시작하는 각 행의 필드/열 수를 나타냅니다 awk.

$ time awk '{c=0; for(i=4;i<=NF;i++) if($i<10 && $i>=0) {
    if(++c==7) {print $0; next} }else{c=0} }' infile
real    0m0.317s
user    0m0.156s
sys     0m0.172s

또는 정규식 모드에서 다시 적용됩니다.원본 파일부동 소수점만 포함된 경우 (플래그와 함께 사용하는 경우)보다 grep더 효율적이고 약 6배 빠른 다음 명령을 사용할 수 있습니다.awk-PGrep -E, Sed -E - "[x]{1,9999}"를 사용할 때 성능이 저하되지만 그 이유는 무엇입니까?), 그러나 awk범위를 변경할 수 있으므로 솔루션의 유연성이 주어지면 + 두 숫자의 정수/부동/혼합인 경우 작동합니다.

$ time grep -P '([^\d]\d\.\d[^\d]){7}' infile
real    0m0.060s
user    0m0.016s
sys     0m0.031s

또는 다른 방법으로:

$ time grep -P '(\s+\d\.\d\s+){7}' infile
real    0m0.057s
user    0m0.000s
sys     0m0.031s

grep또는 sed다음과의 호환성 awk:

$ time grep -E '([^0-9][0-9]\.[0-9][^0-9]){7}' infile
real    0m0.419s
user    0m0.375s
sys     0m0.063s
$ time sed -En '/([^0-9][0-9]\.[0-9][^0-9]){7}/p' infile
real    0m0.367s
user    0m0.172s
sys     0m0.203s
$ time awk '/([^0-9][0-9]\.[0-9][^0-9]){7}/' infile
real    0m0.361s
user    0m0.219s
sys     0m0.172s

관련 정보