나는문서일부 누락된 데이터 포인트에 대한 값이 있으며, 누락된 값은 로 표시됩니다 ****
. 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
-P
Grep -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