숫자로 가득 찬 파일이 있는데 각 줄에는 숫자가 있습니다. 각 숫자는 두 자리 또는 세 자리 숫자로 구성됩니다.
두 개 이상의 연속 숫자가 포함된 임의의 숫자로 파일을 필터링하고 싶습니다. 이러한 연속 숫자는 연속적(예: 127, 215, 781)이거나 불연속적(예: 506)일 수 있습니다. 연속된 숫자의 순서는 중요하지 않습니다. 크기는 작은 것에서 큰 것(예: 127) 또는 큰 것에서 작은 것(예: 215)일 수 있습니다.
예를 들어:
127
215
781
874
370
01
10
142
506
94
예상 출력:
370
94
왜냐하면:
127 # Has two sequential and consecutive digits (1 and 2)
215 # Has two sequential and consecutive digits (1 and 2)
781 # Has two sequential and consecutive digits (7 and 8)
874 # Has two sequential and consecutive digits (7 and 8)
370 # Keep
01 # Has two sequential and consecutive digits (0 and 1)
10 # Has two sequential and consecutive digits (0 and 1)
142 # Has two sequential and non-consecutive digits (1 and 2)
506 # Has two sequential and non-consecutive digits (5 and 6)
94 # Keep
답변1
FS를 빈 문자열로 설정합니다 awk
. 빈 FS를 사용하는 효과는 POSIX별로 정의되지 않은 동작이며 awk
사용 중인 버전에 따라 다른 결과가 발생할 수 있습니다. 다음은 GNU에서 테스트되었습니다 awk
.
awk -F '' '{
is_sequential=0;
for (i=2; i<=NF; i++)
is_sequential+=($0 ~ $i-1 || $0 ~ $i+1)
}!is_sequential' infile
전체 행의 모든 숫자가 숫자-1 또는 숫자+1과 같은지 확인합니다 $i
. 즉, 행에 하나의 숫자 또는 두 개의 숫자가 표시되면 서로 옆에 최소 두 개의 숫자를 찾은 것입니다(섹션 1). , 숫자 자체 및 다음 또는 둘 다(순차적으로), 따라서 값$i-1
$i+1
number-1
number+1
$i
$i-1
$i+1
순차적이다변수는 증가하고 그렇지 않으면 0으로 유지됩니다.
를 사용하여 !is_sequential
값이 변경되지 않은 행을 인쇄합니다(값은 여전히 이며 0
최소 두 개의 연속 숫자가 표시되지 않음).awk 스크립트 끝에 있는 "1"은 무엇을 의미합니까?
또는 awk를 사용하십시오.
awk '{
is_sequential=0;
for (i=1; i<=length(); i++) {
num=substr($0, i, 1)
is_sequential+=($0 ~ num-1 || $0 ~ num+1)
}
}!is_sequential' infile
답변2
시도해 볼 수 있습니다
awk '
{split ("", N) # delete array N
L = 1 # initialise boolean L to TRUE
for (i=1; i<=length($1); i++){ # for each digit
P = substr($1, i, 1)
if (N[P-1] || N[P+1]){ # if contiguous digit exists,
L = 0
break # set L to FALSE; and quit the for loop
}
N[P] = 1
}
}
L
' file
산출:
370
94
또는
awk '
{split ("", N)
L = 1
for (i=1; i<=length; i++)
N[substr($0,i,1)] = 1 # set all N elements for the digits in string
for (i=0; i<9; i++)
if (N[i] + N[i+1] == 2) { # check for two adjacent elements to be TRUE
L = 0
break
}
}
L
' file
산출:
370
94
우분투 18.04에서 테스트되었습니다.
답변3
여기에서는 조합 목록이 상대적으로 작기 때문에 ERE 대체에서 이를 고려할 수도 있습니다.
grep -vE '0.*1|1.*[02]|2.*[13]|3.*[24]|4.*[35]|5.*[46]|6.*[57]|7.*[68]|8.*[79]|9.*8'
이와 동일 perl
하지만 정규 표현식 내에서 Perl 코드를 사용하여 (??{...})
다음 또는 이전 숫자와 일치시킵니다.
perl -ne 'print unless /([0-8]).*(??{$1+1})/ || /([1-9]).*(??{$1-1})/'
sed를 사용하면 패턴 공간에 연속 쌍 목록을 추가하고 역참조를 사용하여 일치하는 항목을 찾을 수 있습니다.
sed -ne '1{x;s/$/0123456789876543210/;x;}' -e 'G;/\(.\).*\(.\).*\n.*\1\2/!P'