これは簡単なはずですが、理解できません。 sedを使用してAまたはBをCに置き換えるには、コードは次のようになります。
$ echo AAXXAAYYBB | sed 's/[AB]/C/g'
CCXXCCYYCC
これにより、AとBの両方がCに変換されます。
私が望むのは、「A」を2つ(またはそれ以上)の変数の1つに置き換えることです。
入力する:
AAXXAAYYBB
パスワード:
sed 's/A/[BC]/g'
出力(BまたはCの交換がランダムである場合):
BCXXCBYYBB
ただし、このコードはAを次にのみ変更します。
$ echo AAXXAAYYBB | sed 's/A/[BC]/g'
[BC][BC]XX[BC][BC]YYBB
可能であれば、ここではPERLを使用しないようにしています。この問題を解決する方法を知っている人はいますか?
答え1
交換可能最初次のような文字列:
${str/A/...}
また、以下を使用して任意の(暗号的に安全な数値ではなく)値を生成できます。
r=(B C)
${r[RANDOM%2]}
変数がr
展開されるたびに。
同じですが、より速い操作は、ANDを使用して値の最後のビットを抽出することです。${r[RANDOM&1]}
だから:
#!/bin/bash
str=AAXXAAYYBB
r=(B C)
while [ "${str%"${str#*A}"}" ]; do # while there is an A to change
str=${str/A/"${r[RANDOM&1]}"}
done
echo "str=$str"
呼び出されるたびにランダムな結果が生成されます。
ボスケスリー
#!/bin/sh
str=AAXXAAYYZZAAA
while [ "${str%"${str#*A}"}" ]; do # while there is an A.
r=$(od -An -tu1 -N 1 /dev/urandom) # get one random byte
r=$((r&1)) # Is it even or odd?
if [ "$r" -eq 0 ]; then s=B; else s=C;fi # Select B or C
str="${str%%A*}${s}${str#*A}" # Change the string.
done
echo "str=$str"
おそらく、ほとんどの場合、より速く組み込まれたprintfを使用して、より簡単ですが、より不思議な方法で任意のバイトを読み取ることができます。
r=$(printf '%d\n' "'$(head -c1 /dev/urandom)")
答え2
Sedではありませんが、Perlは避けてください。
$ echo AAXXAAYYBB | gawk '
BEGIN{srand()}
{
n = patsplit($0,a,/A/,s);
for(i=1;i<=n;i++) printf("%s%s", rand() < 0.5 ? "B" : "C", s[i]);
print ""
}
'
CBXXCCYYBB
答え3
スクリプトを使用すると、この特定の猫のスキンを作成する方法はいくつかありますが、ここに私がまとめたものがあります。ビューには良くないかもしれませんが(bashシェルに依存しています!)、役に立ちます。
#!/bin/bash
TEXT="AAXXAAYYBB"
echo "Start: $TEXT"
# So long as there are un-converted 'A' in the input string...
while [[ "$TEXT" =~ A ]]
do
# .. convert one 'A' to a random choice of either 'B' or 'C'
TEXT=$(echo $TEXT | sed -e "s/A/$(((RANDOM%2>0))&&echo B || echo C)/")
# lets show how we are progressing...
echo "Progress: $TEXT"
done
# No more 'A' in the input string, we are done:
echo "End: $TEXT"
出力例:
最初の実行:
Start: AAXXAAYYBB
Progress: BAXXAAYYBB
Progress: BBXXAAYYBB
Progress: BBXXBAYYBB
Progress: BBXXBCYYBB
End: BBXXBCYYBB
2回目の実行:
Start: AAXXAAYYBB
Progress: CAXXAAYYBB
Progress: CBXXAAYYBB
Progress: CBXXCAYYBB
Progress: CBXXCBYYBB
End: CBXXCBYYBB
答え4
Perlは正規表現が好きです。
Perlを使用することを選択した場合は、このe
フラグを置き換えるのに役立ちます。これはe
コード置換を評価します。
たとえば、
s/A/c("BC")/eg
cは文字列から任意の文字を抽出するサブルーチンです。
A-> [BC]を使ってハードコードします。
sub c {
if(my $s = shift) {
my $index = int(rand(length($s)));
return substr($s, $index, 1);
}
}
while(<<>>){
print s/A/C("BC")/eg
}
あるいは、あまりきれいではない1行の詩に圧縮されることもあります。 (明確にするために実際には2行):
perl -E 'sub c {if(my $l = shift) {substr($l, int(rand(length($l))), 1);}}' -plE 's/A/c(BCBBB)/eg'
random_replace に展開します。
#!/usr/bin/env perl
use strict;
use warnings;
die "usage: random_replace regex string_of_replacement_chars\n" unless @ARGV == 2;
my $search = shift;
my $replace = shift;
sub c {
if (my $s = shift) {
my $index = int(rand(length($s)));
substr($s, $index, 1);
}
}
while(<<>>)
{
s/$search/c($replace)/eg;
print;
}
% echo "AAAAAA" | ./random_replace A BC
CCCCBC
% echo "AAAAAA" | ./random_replace A BC
BBBBBC
追加ボーナスで検索は正規表現にすることができます。 A または B を C または D に変更したいとしましょう。
% echo "AAABBB" | ./random_replace '[A-B]' CD
CCCDCD
% echo "AAABBB" | ./random_replace '[A-B]' CD
DDCCDD