같은 숫자가 있는 모든 행에서 숫자를 증가시키는 방법

같은 숫자가 있는 모든 행에서 숫자를 증가시키는 방법

샘플 파일은 다음과 같습니다.

test test test test test
TEST: 15000
abcabc TEST: 15000 testtest test
TEST: 15000
test test  test 14000 test test test
TEST: 15000
TEST: 15000

15000이 보이면 텍스트가 무엇이든 그렇게 되어야 합니다. 각 줄에 1을 추가하면 됩니다.

test test test test test
TEST: 15001
abcabc TEST: 15002 testtest test
TEST: 15003
test test  test 14000 test test test
TEST: 15004
TEST: 15005

답변1

그리고 perl:

$ cat file
TEST: 15000
TEST: 15000
TEST: 15000 15000 -15000 015007 15000e-1 1.15000
OTHER: 1000 1000 1000
AND: 1000 1000 0x14999 14999
$ perl -pe 's{\d+}{$& + ++$c{$&}}ge' file
TEST: 15001
TEST: 15002
TEST: 15003 15004 -15005 15008 15006e-2 3.15007
OTHER: 1001 1002 1003
AND: 1004 1005 1x15000 15001
$ perl -pe 's{\d+}{$& + $c{$&}++}ge' file
TEST: 15000
TEST: 15001
TEST: 15002 15003 -15004 15007 15005e-1 2.15006
OTHER: 1000 1001 1002
AND: 1003 1004 0x14999 15000

십진수 시퀀스만 처리합니다. 따라서 입력이 양의 십진 정수가 아닌 경우 위에 표시된 대로 예상한 결과를 제공하지 못할 수 있습니다.

위의 015000은 여전히 ​​10진수(8진수 아님)로 간주되지만 비교가 숫자가 아닌 어휘이므로 15000과 동일한 것으로 간주되지 않습니다. 숫자 비교를 $c{$&}위해 다음으로 바꿉니다 ( 각 고유 숫자의 증분을 기억하는 $c{0+$&}연관 배열에 대한 키로 사용되는 숫자를 정규화하여 ).%c

모든 숫자가 구별되도록 하는 것이 목적이라면 그렇게 하지 않는다는 점에 유의하세요. 15000의 첫 번째 발생이 어떻게 위에서 14999의 두 번째 발생과 동일한 숫자로 변환되는지 확인하세요.

또한 2 64 - 1(18446744073709551615) 보다 큰 숫자는 과학적 표기법으로 표현되며 정밀도가 떨어집니다. Add는 -Mbignum임의로 큰 숫자를 처리할 수 있지만 작업에 1을 삽입하여 bignum으로 변환해야 합니다.

$ perl -pe 's{\d+}{$& + ++$c{$&}}ge' <<< 99999999999999999999
1e+20
$ perl -Mbignum -pe 's{\d+}{0 + $& + ++$c{$&}}ge' <<< 99999999999999999999
100000000000000000000

답변2

$ awk '{$2 += ++i}1' test.txt 
TEST: 15001
TEST: 15002
TEST: 15003

증가 i시켜 에 추가합니다 $2.

그런데 변수가 i처음 증가할 때는 존재하지 않으므로 초기 값으로 생성된 0다음 다음으로 증가됩니다.1 앞으로필드 2에 추가됩니다. 대신 i++에 썼다면 ++i증가했을 것입니다.뒤쪽에$2에 초기값(0)이 추가됩니다.

$2 = 15000인 경우에만 행 수를 늘리려면 다음을 수행하십시오.

awk '$2 == 15000 {$2 += ++i}1' test.txt 

또는 perl을 사용하여 perl의 /e정규식 수정자를 사용하여 s/// 연산자의 RHS를 perl 표현식으로 평가합니다.

TEST: 15000.5(예제 입력 끝에 추가 줄을 추가했습니다)

$ perl -p -e 's/\d+/$& == 15000 ? $& + ++$i : $&/eg' input.txt 
test test test test test
TEST: 15001
abcabc TEST: 15002 testtest test
TEST: 15003
test test  test 14000 test test test
TEST: 15004
TEST: 15005
TEST: 15006.5

영어: 연속된 숫자에 대해 숫자가 15000과 같으면 그 자체와 사전 증분된 변수로 바꾸고 $i, 그렇지 않으면 자체로 바꿉니다.

awk와 마찬가지로 $i존재하지 않을 때 사용하면 초기값 0(또는 문자열로 사용하는 경우 빈 문자열)으로 생성됩니다. 그건 그렇고, 이는 변수 이름에 철자가 틀린 경우(또는 변수가 변수 범위 외부에서 사용되는 경우) 런타임 오류의 매우 일반적인 원인이므로 Perl에는 use strict모든 변수 및 기타 식별자가 필요한 pragma가 있습니다.사용하기 전에 선언. 선언되지 않은 변수를 사용하면 컴파일 타임 오류가 발생하므로 잘못된 프로그램을 실행하여 피해가 발생하기 전에 오류를 찾아서 수정할 수 있습니다. 이것은 단순한 한 줄짜리이고 하나의 변수만(한 번만) 사용하므로 strict여기서는 사용하지 않습니다.

또는 가능하다면 15000.5입력에 비슷한 숫자가 있을 수 있으며아니요바라건대 그들은 또한 증가할 것입니다 ++$i:

$ perl -p -e 's/(\d+)([^.])/($1 == 15000 ? $1 + ++$i : $1) . $2/eg' input.txt
test test test test test
TEST: 15001
abcabc TEST: 15002 testtest test
TEST: 15003
test test  test 14000 test test test
TEST: 15004
TEST: 15005
TEST: 15000.5

이 버전은 두 가지 패턴, 즉 숫자(예: $1)와 숫자 뒤의 모든 문자(예: $2)를 캡처합니다. 단 해당 문자는 소수점( .)이 아닙니다. 쉼표 등을 사용하는 로케일에서는 이를 변경해야 할 수도 있습니다. 일치에 성공하면 첫 번째 Perl 버전과 동일하게 대체 항목이 계산되지만 .Perl의 문자열 연결 연산자( )를 사용하여 $2가 추가됩니다.

관련 정보