我如何通过添加 n+number 来转换行
How can i convert lines with adding n+number
如何使用 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')......
I want 1000 + n so it should be 1000 + 1 = 1001 or 1000 + 25 = 1025
instead of 100025
这是一个相当复杂的 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')
通过 Perl,
$ echo "(1,1,'country1'),(2,1,'country2'),(3,1,'country3')....." | perl -pe 's/\(\K(\d+)/1000+/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+/eg;s/,\K(\d+)/1000+/eg'
(5001,1001,'city'),(5002,1002,'city2'),(5033,1033,'city3').....
\K
丢弃之前匹配的字符,e
修饰符有助于对替换部分进行一些算术运算。
考虑这个例子。
's/\(\K(\d+)/1000+/eg'
\(
匹配文字 (
符号。
\K
从考虑中丢弃先前匹配的 (
字符。这就像一个积极的回头看。 \(\K
会写成 (?<=\()
。 Next (\d+)
捕获以下一位或多位数字。现在这个数字存储在组索引 1 中。
- 所以
(
加上后面的数就被这个1000+
算术运算的输出匹配替换了。请注意,</code> 指的是位于组 index1 内的数字。如果存储的数字是 <code>1
,那么 1000+1
会产生 1001
,这是替换字符串。
g
修饰符有助于进行全局匹配。
e
修饰符允许替换部分的算术函数。
好吧,这有点老套(请注意,所有使用 awk 或 sed 试图绕过构建合适的解析器的方法都将是),但是如果您的文件格式与您制定的一样严格看,然后
awk 'BEGIN { RS = "("; ORS=""; FS = ","; OFS = FS } NF == 0 { next } { += 5000; if(index(, "country") == 2) += 1000; print RS [=10=] }' 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:
+= 5000 # First field increased by 5000
if(index(, "country") == 2) { # Second field increased by 1000 if it
+= 1000 # describes a country
}
print RS [=11=] # print the whole shebang
}
这需要一点解释。
因为 RS
是 (
,记录是 1,1,'country1'),
、2,1,'country2'),
等等(重要的是,包括末尾的 ),
。
由于 FS
是 ,
,在第一条记录的示例中,字段是 1
、1
、'country1')
和一个空标记.
由于 ORS
为空,awk 不会在输出时在记录之间放置记录分隔符。
由于 OFS
与 FS
相同,字段在输出中的分隔方式与在输入中的分隔方式相同。
然后:
print RS [=12=]
打印以逗号分隔的所有字段 (OFS
= FS
= ","
),前面加上一个 openparen(RS
是什么),然后是输出记录分隔符——它是空的。因此格式与输入中的格式保持一致,实际上只有我们更改的字段发生了更改。
vim解决方案
对于第一种情况:只有第一个数字会增加1000:
:%s/(\zs\d\+/\=submatch(0)+1000/g
对于第二个例子:必须更改两个数字,第一个数字+5k,第二个数字+1k:
:%s/\v\(\zs(\d+),(\d+)/\=string(submatch(1)+5000).','.string(submatch(2)+1000)/g
如何使用 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')......
I want 1000 + n so it should be 1000 + 1 = 1001 or 1000 + 25 = 1025 instead of 100025
这是一个相当复杂的 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')
通过 Perl,
$ echo "(1,1,'country1'),(2,1,'country2'),(3,1,'country3')....." | perl -pe 's/\(\K(\d+)/1000+/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+/eg;s/,\K(\d+)/1000+/eg'
(5001,1001,'city'),(5002,1002,'city2'),(5033,1033,'city3').....
\K
丢弃之前匹配的字符,e
修饰符有助于对替换部分进行一些算术运算。
考虑这个例子。
's/\(\K(\d+)/1000+/eg'
\(
匹配文字(
符号。\K
从考虑中丢弃先前匹配的(
字符。这就像一个积极的回头看。\(\K
会写成(?<=\()
。 Next(\d+)
捕获以下一位或多位数字。现在这个数字存储在组索引 1 中。- 所以
(
加上后面的数就被这个1000+
算术运算的输出匹配替换了。请注意,</code> 指的是位于组 index1 内的数字。如果存储的数字是 <code>1
,那么1000+1
会产生1001
,这是替换字符串。 g
修饰符有助于进行全局匹配。e
修饰符允许替换部分的算术函数。
好吧,这有点老套(请注意,所有使用 awk 或 sed 试图绕过构建合适的解析器的方法都将是),但是如果您的文件格式与您制定的一样严格看,然后
awk 'BEGIN { RS = "("; ORS=""; FS = ","; OFS = FS } NF == 0 { next } { += 5000; if(index(, "country") == 2) += 1000; print RS [=10=] }' 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:
+= 5000 # First field increased by 5000
if(index(, "country") == 2) { # Second field increased by 1000 if it
+= 1000 # describes a country
}
print RS [=11=] # print the whole shebang
}
这需要一点解释。
因为 RS
是 (
,记录是 1,1,'country1'),
、2,1,'country2'),
等等(重要的是,包括末尾的 ),
。
由于 FS
是 ,
,在第一条记录的示例中,字段是 1
、1
、'country1')
和一个空标记.
由于 ORS
为空,awk 不会在输出时在记录之间放置记录分隔符。
由于 OFS
与 FS
相同,字段在输出中的分隔方式与在输入中的分隔方式相同。
然后:
print RS [=12=]
打印以逗号分隔的所有字段 (OFS
= FS
= ","
),前面加上一个 openparen(RS
是什么),然后是输出记录分隔符——它是空的。因此格式与输入中的格式保持一致,实际上只有我们更改的字段发生了更改。
vim解决方案
对于第一种情况:只有第一个数字会增加1000:
:%s/(\zs\d\+/\=submatch(0)+1000/g
对于第二个例子:必须更改两个数字,第一个数字+5k,第二个数字+1k:
:%s/\v\(\zs(\d+),(\d+)/\=string(submatch(1)+5000).','.string(submatch(2)+1000)/g