이것은 간단해야하지만 알아낼 수 없습니다. sed를 사용하여 A 또는 B를 C로 바꾸려면 코드는 다음과 같습니다.
$ echo AAXXAAYYBB | sed 's/[AB]/C/g'
CCXXCCYYCC
이로 인해 A와 B가 모두 C로 변환됩니다.
내가 원하는 것은 "A"를 두 개(또는 그 이상) 변수 중 하나로 바꾸는 것입니다.
입력하다:
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
두 번째 실행:
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
}
아니면 별로 예쁘지 않은 한 줄의 시로 압축되기도 합니다. (명확성을 위해 실제로는 두 줄):
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