연속된 각 숫자를 "1"씩 줄이는 스크립트를 작성하려고 하는데 얻은 것은 "0"뿐입니다.
awk '{a=gensub(/([0-9]+)/,"\\1","g",$0);
if(a~/[0-9]+/) {gsub(/[0-9]+/,a-1,$0);}
print $0}'
예를 들어 문자열은 다음과 같습니다.
1,2,3,4-7
결과는 다음과 같습니다.
0,1,2,3-6
대신 나는 다음을 얻습니다.
0,0,0,0-0
답변1
awk
대체 기능은 상당히 제한적입니다. 일치하는 부품 중 적어도 일부가 교체품에 포함될 gawk
수 있지만 해당 부품에 대한 작업은 수행할 수 없습니다.gensub()
작동 awk
하지만 다른 접근 방식을 취해야 합니다.
awk '{
text = $0
$0 = ""
while (match(text, /[0-9]+/)) {
$0 = $0 substr(text, 1, RSTART-1) \
(substr(text, RSTART, RLENGTH) - 1)
text = substr(text, RSTART+RLENGTH)
}
$0 = $0 text
print}'
또는 awk
@jofel의 방법의 변형으로 GNU를 사용하십시오.
gawk -v 'RS=[0-9]+' '{printf "%s", $0 (RT==""?"":RT-1)}'
또는
gawk -v 'RS=[^0-9]+' '{printf "%s",($0==""?"":$0 - 1)RT}'
그러나 여기에서 사용하는 것이 더 쉽습니다 perl
.
perl -pe 's/\d+/$&-1/ge'
perl
캡처 그룹(예 $1
: , $2
... 및 $&
전체 일치 부분)을 사용할 수 있으며, 이 e
플래그를 사용하여 이러한 캡처 그룹을 사용하여 임의의 표현식을 실행할 수 있습니다 perl
.
답변2
귀하의 awk 솔루션은 첫 번째 숫자만 일치한 다음 다른 모든 숫자를 첫 번째 숫자에서 1을 뺀 숫자로 바꿉니다.
프로그램의 경우 gawk
GNU의 awk()와 함께 사용할 수 있습니다.
awk 'BEGIN { RS="[^0-9]"; OFS=""; ORS=""; } {a=gensub(/([0-9]+)/,"\\1","g",$0);if(a~/[0-9]+/) {gsub(/[0-9]+/,(a-1),$0);} print $0,RT}'
하지만 이는 다음과 같이 단순화될 수 있습니다.
awk 'BEGIN { RS="[^0-9]"; OFS=""; ORS=""; } {if(length($0)) {print ($0-1);}print RT}'
또는 댓글을 추가하세요.
awk '
BEGIN {
RS="[^0-9]"; # set the record separator to a regexp matching all
OFS=""; # no output field separator
ORS=""; # no output record separator (we use RT)
}
{
if(length($0)) { # if number found
print ($0-1); # print it decreased by one
}
print RT # output current field separator (=non-digit).
}'
숫자가 아닌 각각은 레코드 구분 기호로 사용되며 print 문과 함께 다시 삽입됩니다.
Python 솔루션은 다음과 같습니다.
python -c 'import re,sys; print re.compile("\d+").sub(lambda i: str(int(i.group())-1),sys.stdin.read()),'
답변3
일반(GNU가 아닌) "awk"를 사용하십시오.
입력 줄을 값과 구분 기호 배열로 분할하는 것이 좋습니다. 그런 다음 값을 수정하고 구분 기호로 다시 그룹화합니다.
awk '{
split("0," $0 ",0", numbers, "[^0-9]+"); # make sure each line starts and ends with a number
split($0, sep, "[0-9]+");
res = ""; j = 1;
for (i = 2; i < length(numbers); i ++) { # ignore the dummy numbers added above
res = res sep[j++] (numbers[i] - 1);
}
print res;
}' file