連続した各数字を「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