#!/bin/bash
#input/output strings
input=tomfoolery
d=fOo;
e=bar;
# turn replacement strings into character-arrays
D=($(echo $d |grep -o .))
E=($(echo $e |grep -o .))
# define output as empty
o=""
# permutate over the individual characters of 'd' and set the case of the corresponding character in 'e'
for i in $(seq 0 $((${#D[@]}-1)) );do
printf "${D[i]} --> "; # for debugging only
if [[ $(echo ${D[i]} |grep -c '[A-Z]') -eq 1 ]]; then
echo ${E[i]} |tr '[a-z]' '[A-Z]'; # for debugging only
o=${o}$(echo ${E[i]} |tr '[a-z]' '[A-Z]');
else
echo ${E[i]}; # for debugging only
o=${o}${E[i]};
fi;
done
echo "$o" # for debugging only
echo $input |sed "s@$d@$o@i"
我通常不会回答不包含OP尝试自己解决问题的问题,但是已经发布了多个答案,并且在awk中很容易做到(如果OP有sed,那么OP将在他们的系统上执行此操作) )所以...使用任何 awk (为了清楚起见,使用比必要的变量更多的变量):
如果输入可能比您的替换字符串长,并且您只想在这种情况
repStr
下重复字符,那么只需在后面添加此内容即可将长度加倍,直到足够长:repStr
oldStr = $0
repStr
这是一个奇怪的要求,但却是一个很好的脑筋急转弯。然而,我的解决方案仅适用于相同长度的字符串 - 因为否则,没有信息来定义输出的情况。
Nether 工具具有直接执行此操作的功能。对于 POSIX,
sed
很难想出比枚举替换更好的方法:一些现代
sed
版本具有非标准 Perl 便利性,例如\L
大小写转换,但仍然没有方便的方法来测试输入字符的大小写。使用 Awk,至少您可以从输入生成此脚本。
这会生成一个位图来指导逻辑,同时生成替换数组
s
;当当前位置的位为1时,我们选择当前字符的小写版本,否则选择大写版本。常规 Awk 没有按位运算符,因此我们使用常规算术来计算当前位的值。(GNU Awk 支持按位逻辑,但实际上,它不会简化这么多。)如果字符串长度不同,Awk 解决方案将退出并出现错误。
演示:https://ideone.com/liZ3nh
对于 Perl,我想这会更简单一些;但你询问了 awk
sed
或 awk 解决方案,所以我没有去那里。这两种解决方案都将进行传递替换,即如果您的替换字符串与输入字符串匹配,您可以获得多个替换,具体取决于它们重叠的程度。(防止这种情况并不难;
t
中的命令sed
表示如果先前的替换更改了某些内容,则跳过当前行的脚本的其余部分;在 Awk 中,您可以nextline
在存在匹配时执行此操作。)