使用 sed 将每个字符替换为自身后跟 $n 次的字符?

Use sed to replace every character by itself followed by $n times a char?

我正在尝试 运行 下面的命令将 DECEMBER 中的每个字符替换为本身后跟 $n 问号。我试过像 {$n} 这样转义 {$n} 并保持原样。然而我的输出一直是 D?{$n}E?{$n}...难道用 sed 就不可能做到这一点吗?

我怎么知道这个。

echo 'DECEMBER' > a.txt
sed -i "s%\(.\)%\(?\){$n}%g" a.txt
cat a.txt

范围(也称为区间或限制量词),如 {3} / {3,} / {3,6},是 regex 的一部分,并且不是 替换 模式。

您可以使用

sed -i "s/./&$(for i in {1..7}; do echo -n '?'; done)/g" a.txt

online demo

#!/bin/bash
sed "s/./&$(for i in {1..7}; do echo -n '?'; done)/g" <<< "DECEMBER"
# => D???????E???????C???????E???????M???????B???????E???????R???????

这里,. 匹配任何字符,替换模式中的 & 将它放回去,$(for i in {1..7}; do echo -n '?'; done) 在它后面添加七个问号。

这可能适合您 (GNU sed):

n=5
sed -E ':a;s/[^\n]/&\n/g;x;s/^/x/;/x{'"$n"'}/{z;x;y/\n/?/;b};x;ba' file

将换行符附加到一行中的每个非换行符 $n 次,然后用预期字符替换所有换行符 ?

N.B。换行符被选为初始替换字符,因为它不可能位于一行内(sed 使用换行符分隔行),如果当前行中已经存在最终替换字符,则替换是正确的。

在设置 n=2 后,在每个 Unix 机器上的任何 shell 中有效地使用任何 awk:

$ awk -v n="$n" '
    BEGIN {
        new = sprintf("%*s",n,"")
        gsub(/./,"?",new)
    }
    {
        gsub(/./,"&"new)
        print
    }
' a.txt
D??E??C??E??M??B??E??R??

要“就地”进行更改,请将 GNU awk 与 -i inplace 一起使用,就像 GNU sed 具有 -i.

警告 - 如果您要在替换文本中使用的字符是 & 那么您需要在 BEGIN 部​​分使用 gsub(/./,"\\\&",new) 以使其被视为文字而不是反向引用元字符。使用任何 sed 解决方案和任何在脚本周围使用双引号的解决方案在处理 $ 时都会遇到更多问题(例如处理 </code> 或 <code>/)具有 shell 扩展未加引号的脚本的解决方案在通配字符方面会有更多问题。

这条单线应该可以解决问题:

sed 's/./&'$(printf '%*s' "$n" '' | tr ' ' '?')'/g' a.txt

假设 $n 扩展为正整数并且命令在 POSIX shell.

中执行