1

很抱歉这个看似简单的问题,但花了太长时间试图在任何地方找到解决方案并尝试不同的 sed 选项。我只需要用逗号替换文本文件中的所有点,但只是在两个位置之间。例如,来自:

1.3.5.7.9

1.3,5,7.9

所以,更换 . ,在位置 3 到 7 之间。谢谢!

编辑:对不起,我假装简化了问题,但由于我的问题缺乏细节,前 3 个答案都不起作用,让我再深入一点。重要的一点是在不知道字符串的其余部分的情况下用逗号替换位置间隔中的所有点:

Here some text. I don't want to change. 10.000 usd  234.566 usd Continuation text.
More text. No need to change this part.    345 usd   76.433 usd Text going on. So on.

这是一个固定宽度的文本文件,以列为单位,我需要更改数字的国际格式,用逗号替换点。我只知道我需要搜索并最终替换点的初始和最终位置。显然,并不是所有的数字都有点(只有超过 1000 个的)。谢谢。

4

5 回答 5

2

澄清问题后重写答案:

这很难处理sed,但可以使用其他标准实用程序来简化,例如cutand paste

$ start=40
$ end=64
$ paste -d' ' <(cut -c -$((start-1)) example.txt) \
> <(cut -c $((start+1))-$((end-1)) example.txt | sed 'y/./,/') \
> <(cut -c $((end+1))- example.txt)
Here some text. I don't want to change. 10,000 usd  234,566 usd Continuation text.
More text. No need to change this part.    345 usd   76,433 usd Text going on. So on.

>只是表示上一行的延续。<是真实的)。这当然是非常低效的,但在概念上很简单。

我用了所有的+1东西-1来摆脱多余的空间。不确定你是否需要它。

一个纯 sed 解决方案(支撑自己):

$ sed "s/\(.\{${start}\}\)\(.\{$((end-start))\}\)/\1\n\2\n/;h;s/.*\n\(.*\)\n.*/\1/;y/./,/;G;s/^\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)$/\2\1\4/" example.txt
Here some text. I don't want to change. 10,000 usd  234,566 usd Continuation text.
More text. No need to change this part.    345 usd   76,433 usd Text going on. So on.

GNU sed

$ sed -r "s/(.{${start}})(.{$((end-start))})/\1\n\2\n/;h;s/.*\n(.*)\n.*/\1/;y/./,/;G;s/^(.*)\n(.*)\n(.*)\n(.*)$/\2\1\4/" example.txt 
Here some text. I don't want to change. 10,000 usd  234,566 usd Continuation text.
More text. No need to change this part.    345 usd   76,433 usd Text going on. So on.
于 2013-02-04T18:19:15.627 回答
1

这在 pure 中做起来相当尴尬sed。如果您不受严格限制sed,我建议您使用其他工具来执行此操作。Ed Mortongawk基于 - 的解决方案可能是解决这个问题的最不尴尬(没有双关语)的方法。

这是一个sed用于完成繁重工作的示例,但为简单起见,将其包装在 bash 函数中:

function transform () {
    line=$1
    start=$2
    end=$3
    # Save beginning and end of line
    front=$(echo $line | sed -e "s/\(^.\{$start\}\).*$/\1/")
    back=$(echo $line | sed -e "s/^.\{$end\}//")
    # Translate characters
    line=$(echo $line | sed -e 'y/\./,/')
    # Restore unmodified beginning/end
    echo $line | sed -e "s/^.\{$start\}/$front/" -e "s/\(^.\{$end\}\).*$/\1$back/"
}

像这样调用这个函数:

$ transform "1.3.5.7.9" 3 7
1.3,5,7.9
于 2013-02-05T23:45:33.567 回答
1
$ echo "1.3.5.7.9" |
gawk -v s=3 -v e=7 '{
   print substr($0,1,s-1) gensub(/\./,",","g",substr($0,s,e-s+1)) substr($0,e+1)
}'
1.3,5,7.9
于 2013-02-04T19:17:42.437 回答
1


我尝试简化正则表达式,但它更宽松。

echo 1.3.5.7.9 | sed -r "s/^(...).(.).(..)/\1,\2,\3/"
1.3,5,7.9

PS:它不适用于 BSD sed。

于 2013-02-04T19:08:02.793 回答
0

谢谢你们。我发现(不是我的优点)作为简单的解决方案是:

  1. 对于固定宽度文件:

    awk -F "" 'OFS="";{for (j=2;j<= 5;j++) if ($j==".") $j=","}'1
    

将从第 2 个位置到第 5 个位置将所有点更改为逗号。

  1. 对于制表符分隔的字段文件:

    awk -F'\t' 'OFS="\t" {for (j=2;j<=5;j++) gsub(/\./,",",$j)}'1
    

将从第 2 场到第 5 场将所有点变为昏迷。

希望可以帮助某人:无法想象一开始会如此艰难。

于 2013-02-06T09:23:22.043 回答