如何使用sed或正则表达式转换以下行?
(1,1,'country1'),(2,1,'country2'),(3,1,'country3').....
到
(1001,1,'country1'),(1002,1,'country2'),(1003,1,'country3')......
和
(1,1,'city'),(2,2,'city2'),(33,33,'city3').....
到
(5001,1001,'city1'),(5002,1002,'city2'),(5033,1033,'city3')......
我想要1000 + n所以它应该是1000 + 1 = 1001或1000 + 25 = 1025 而不是100025
答案 0 :(得分:3)
对于第一种情况:只有第一个数字会增加1000:
:%s/(\zs\d\+/\=submatch(0)+1000/g
对于第二个例子:必须更改两个数字,第一个数字+ 5k,第二个数字+ 1k:
:%s/\v\(\zs(\d+),(\d+)/\=string(submatch(1)+5000).','.string(submatch(2)+1000)/g
答案 1 :(得分:0)
这是一个非常复杂的perl单行
perl -F'[(]' -ane '
BEGIN {@add=(shift,shift)}
print join "(", map {
@t = split /,/,$_,-1;
for $i (0,1) {$t[$i] += $add[$i] if $t[$i]}
join ",", @t
} @F
' 5000 1000 <<END
(1,1,'city'),(22,22,'city2'),(333,333,'city3')
END
(5001,1001,'city'),(5022,1022,'city2'),(5333,1333,'city3')
答案 2 :(得分:0)
通过Perl,
$ echo "(1,1,'country1'),(2,1,'country2'),(3,1,'country3')....." | perl -pe 's/\(\K(\d+)/1000+$1/eg'
(1001,1,'country1'),(1002,1,'country2'),(1003,1,'country3').....
$ echo "(1,1,'city'),(2,2,'city2'),(33,33,'city3')....." | perl -pe 's/\(\K(\d+)/5000+$1/eg;s/,\K(\d+)/1000+$1/eg'
(5001,1001,'city'),(5002,1002,'city2'),(5033,1033,'city3').....
\K
会丢弃先前匹配的字符,而e
修饰符有助于对替换部分执行某些算术运算。
考虑这个例子。
's/\(\K(\d+)/1000+$1/eg'
\(
匹配文字(
符号。\K
会丢弃之前匹配的(
字符。它就像一个积极的lookebhind。 \(\K
将被写为(?<=\()
。下一个(\d+)
会捕获以下一个或多个数字。现在这个数字存储在组索引1中。(
加上以下数字匹配,并由此1000+$1
算术运算的输出替换。请注意,$1
是指位于index1组内的数字。如果存储的数字是1
而不是1000+1
,则会产生1001
,这是替换字符串。g
修饰符有助于进行全局匹配。e
修饰符允许替换部件上的算术功能。答案 3 :(得分:0)
嗯,这有点非常hackish(请注意,所有使用awk或sed的方法都试图绕过构建正确的解析器),但如果你的文件格式与你看起来一样严格,然后
awk 'BEGIN { RS = "("; ORS=""; FS = ","; OFS = FS } NF == 0 { next } { $1 += 5000; if(index($3, "country") == 2) $2 += 1000; print RS $0 }' filename
应该有效。那是
BEGIN {
RS = "(" # record separator
ORS = "" # output record separator
FS = "," # field separator
OFS = FS # output field separator
}
NF == 0 { next } # lines without fields skipped (that is the
# virtual record before the first openparen)
{ # then for each line:
$1 += 5000 # First field increased by 5000
if(index($3, "country") == 2) { # Second field increased by 1000 if it
$2 += 1000 # describes a country
}
print RS $0 # print the whole shebang
}
这需要一点解释。
由于RS
为(
,所以记录为1,1,'country1'),
,2,1,'country2'),
等等(最重要的是,包括最后的),
。
由于FS
为,
,因此在第一条记录的示例中,字段为1
,1
,'country1')
和空标记。< / p>
由于ORS
为空,因此awk在输出时不会在记录之间放置记录分隔符。
由于OFS
与FS
相同,因此字段将在输出中与输入中的字段相同。
然后:
print RS $0
打印以逗号分隔的所有字段(OFS
= FS
= ","
),前面是openparen(这是RS
),后跟输出记录分隔符 - 它是空的。因此格式保持与输入中的格式相同,只有我们更改的字段实际上已更改。