对于bash中的每一行,将n个字符的字符串替换为n个字符的随机字符串

时间:2019-07-23 18:53:24

标签: bash random replace

我有一个名为tmp.txt的文件。它在制表符分隔文件的一侧用空格分隔的字符“ a-z”和数字“ 0-9”。另一方面。对于每一行,我想随机替换1-3个字符。我的tmp.txt看起来像这样:

s h e h a d y o u r 0.9472 0.2074 0.4878 0.2227 0.4998 0.2841 0.5323 0.4254 0.539 0.4981  
d o n t a s k m e t o c a r r y 0.9741 0.0999 0.338 0.0572 0.4514 0.223 0.5036 0.3835 0.4844 0.6306 
e v e n t h e n 0.8549 0.1265 0.5248 0.2713 0.622 0.2011 0.4334 0.4137 0.4788 0.5435

到目前为止,我已经写了这么多脚本:

cat tmp.txt | while IFS= read -r line; 
    do 
        for i in {1..3}; 
        do 
            a=$(tr -dc 'a-z0-9' | head -c $i);
            b=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c $i);
            sed -i 's/$a/$b/g';
        done; 
    done

自从我得到之后,sed似乎并没有找到$ line。

sed: no input files
sed: no input files
sed: no input files

我以为我仍然在此循环的read -r行内,但看来我错了。有人知道我在做什么错吗?

预先感谢

1 个答案:

答案 0 :(得分:2)

根本不使用sed特别是,不要为每行输入单独运行它三遍:命令替换很慢,而外部命令调用很慢甚至更慢。

#!/usr/bin/env bash
case $BASH_VERSION in ''|[0-3].*|4.0*) echo "ERROR: Bash 4.1+ required" >&2; exit 1;; esac

# Open a continuous stream of acceptable random characters
exec {random_chars_fd}< <(tr -dc 'a-z0-9' </dev/urandom)

while IFS= read -r line; do
  for ((i=0; i<3; i++)); do

    # filter for alpha and numeric characters in our input line
    possible_chars=${line//[![:alnum:]]}

    # pick a random position in the filtered string, and take the character it contains
    char_to_replace=${possible_chars:$(( RANDOM % ${#possible_chars} )):1}

    # now, read one character from our stream of random inputs
    read -n 1 replacement <&$random_chars_fd

    # and replace all instances of the randomly-selected character in our input with the
    # randomly-selected output character.
    line=${line//"$char_to_replace"/"$replacement"}
  done
  printf '%s\n' "$line" # print our new version of the line
done <tmp.txt

一些注释更改:

  • 此代码中的任何地方都没有使用命令替换($(...)或它们的旧反引号语法等效项)。旋转外部命令会导致大量开销,因此应尽可能使用内部bash操作代替;当我们 do 运行一个外部命令时,我们只运行一个副本并将其保留在整个脚本中,而不是一遍又一遍地启动新实例。
  • 所有字符串拼合操作都是使用parameter expansion语法完成的,也在BashFAQ #100中进行了讨论–本机的,内部到流行的操作可以执行替换操作,从字符串中挑选单个字符等
  • 我们不是从cat到循环中,而是重定向。如BashFAQ #24所述,这避免了严重的错误,并且效率更高。