0

我有一个/每行包含许多 's 的文件,例如:

This/is/an/example.
This/is/another/example/to/read.
Read/this/example.
Last/example.

我需要用 替换每行上第一次出现的 ,用 替换/每行上\BEGIN最后一次出现的,以及用/替换\END所有剩余的。例如,上面的文件会变成这样:/\MIDDLE

This\BEGINis\MIDDLEan\ENDexample.
This\BEGINis\MIDDLEanother\MIDDLEexample\MIDDLEto\ENDread.
Read\BEGINthis\ENDexample.
Last\BEGINexample.

如何使用 BASH 或 Linux 上可用的其他工具以这种方式替换此符号,例如grep

4

3 回答 3

4

我会使用sed(你需要sed -Emac OSX 上的扩展正则表达式):

sed -E 's/\//\\BEGIN/; s/\/([^/]+$)/\\END\1/; s/\//\\MIDDLE/g' 

它之所以有效,是因为第一个s命令没有g(全局)标志,所以只有第一次出现的/被替换。第二个s用 替换最后一次出现$,最后最后一次替换替换所有剩余的正斜杠。替换的顺序很重要:如果有一个正斜杠你得到//BEGIN,如果有另一个你得到//END

于 2012-09-15T06:36:28.897 回答
1

您可以尝试 grepping ^([a-zA-Z]+)[](.*)[]([a-zA-Z]+)$ 并将其替换为 $1 /BEGIN $2 /END $3

然后 grep 为所有 \ 并用 /MIDDLE 复制它们

于 2012-09-15T05:29:24.587 回答
1
while IFS=/ read -a f; do (
    set -- "${f[@]}"
                    printf "$1"                       && shift
    (( $# ))     && printf "\\BEGIN$1"                && shift
    (( $# > 1 )) && printf "\\MIDDLE%s" "${@:1:$#-1}" && shift $(( $#-1 ))
    (( $# ))     && printf "\\\\END$1"
                    printf "\n"
    )
done < input.txt

一次读取一行输入,在 / 字符上分割每一行并将结果存储在子shell的位置参数中。第一个字段(我们假设存在)被无条件打印,并且每个剩余字段都打印在正确的分隔符之前。终止换行符无条件打印。

(我不完全确定为什么 END 需要双双反斜杠。没有它,我只打印了 END 的 D。)

于 2012-09-15T16:11:47.137 回答