我有一个包含城市和数字的文件。这是一个csv文件
New York , 23456
chicago, 123,456,789,889981(2-6)
phoenix 123,76(0-3)
文件中的范围编号我想用每个数字替换它。例如,我想将889981(2-6)更改为8899812,8899813,8899814,8899815,8899816并插入同一行。我能用sed吗?它需要扫描整个文件并进行替换。
答案 0 :(得分:4)
sed
算术不是很好;我想这不是不可能,但也不是很简单。我的建议是使用适当的脚本语言,例如awk,perl或python(如果你不熟悉它们,可能是Python;如果你想要尽可能小的内存占用,请使用awk;如果你已经知道Perl ,无论如何,使用Perl)。
perl -pe 's/(\d+)\((\d+)-(\d+)\)$/ join (",",
(join ("", $1, $2) .. join ("", $1, $3))) /ge' file
答案 1 :(得分:2)
不,这超出了你只使用正则表达式所能做的事情。您需要添加更强大的功能,例如perl
,python
或awk
,或者您最喜欢的任何内容。
答案 2 :(得分:1)
使用awk
的解决方案(@glenn jackman可能会发布一些内容
这样做不到5行):
# join.awk --- join an array into a string
function join(array, start, end, sep, result, i)
{
if (sep == "")
sep = " "
else if (sep == SUBSEP) # magic value
sep = ""
result = array[start]
for (i = start + 1; i <= end; i++)
result = result sep array[i]
return result
}
function range(input) {
split(input, a, "[(-)]")
# [1] is startvalue, [2] is start and stop for range
split(a[2], b, "-")
# [1] is start range, [2] is stop range
# create 1st number by appending start range to start value
c[1] = a[1] b[1]
n=2
for(i=b[1]; i<=b[2]; i++){
c[n] = c[n-1] + 1
n++
}
return join(c, 1, b[2], ",")
}
# a line containing a -
/-/ {
for(i=1;i<=NF;i++){
if ($i ~ /-/) {
printf("%s,", range($i))
}
printf("%s,", $i)
}
print ""
}
!/-/{print}
答案 3 :(得分:1)
3参数gawk
函数需要match()
:
gawk '
BEGIN {OFS = FS = ","}
match($NF, /([0-9]+)\(([0-9]+)-([0-9]+)\)/, ary) {
NF--
for (n=ary[2]; n <= ary[3]; n++) {
$(NF+1) = 10 * ary[1] + n
}
}
{print}
'
我假设(基于样本)范围仅出现在最后一个以逗号分隔的字段中。
答案 4 :(得分:0)
这可能对您有用(仅限GNU sed):
sed 's/^\(.*\)\b\([0-9]\+\)(\([0-9]\)-\([0-9]\))/echo "\1" {\2\3..\2\4}/e;s/\([0-9]\),\? \([0-9]\)/\1,\2/g' file
New York , 23456
chicago, 123,456,789,8899812,8899813,8899814,8899815,8899816
phoenix 123,760,761,762,763