【问题标题】:How To Randomly Choose Strings From Same Line In File如何从文件中的同一行中随机选择字符串
【发布时间】:2018-04-04 08:04:06
【问题描述】:

我已阅读这篇文章Select random lines from a file in bashRandom selection of columns using linux command,但是它们不适用于需要保持相同顺序的一组行。我还使用cut 命令搜索了是否有任何随机化选项。

我的尝试:

我正在尝试用新行替换空格,然后随机排序,然后使用 Head 抓取一个随机字符串(对于每一行)。

cat file1.txt | while read line; do echo $line | sed 's/ /\n/g' | sort -R | head -1

虽然这确实为一个随机字符串完成了基本工作,但我想知道是否有更好更有效的方法来编写此代码?这样,我可以添加选项以获取 1-2 个随机字符串,而不仅仅是一个。

这是file1.txt:

#Sample #Example #StackOverflow #Question
#Easy #Simple #Code #Examples #Help
#Support #Really #Helps #Everyone #Learn

这是我想要的输出(随机值):

#Question
#Code #Examples
#Helps

如果您知道实现此代码的更好方法,我将非常感谢您的积极投入和支持。

【问题讨论】:

    标签: linux bash random sed cut


    【解决方案1】:

    这就是解决方案

    while read -r line; do echo "$line" | grep -oP '(\S+)' | shuf -n $((RANDOM%2+1)) | paste -s -d' '; done < file1.txt
    

    【讨论】:

    • 很好的解决方案。正是我想要的。从文件的每一行中随机选择 1-2 个字符串的解决方案。它肯定比我的解决方案好 100 倍。谢谢达比!
    • 很高兴 ;)
    • 嗯,你为什么不把 N 个第一个单词从打乱的行中去掉,就像这样:echo `echo "$line" | grep -oP '(\S+)' | shuf -n $((RANDOM%2+1))` ? AFAIK 所有后续代码并没有真正添加任何 shuf 已经做的事情。
    【解决方案2】:

    使用 AWK:

    %awk 'BEGIN { srand() } { print $(1+int(rand()*NF))}' data.txt
    
    #Question
    #Help
    #Support
    

    您可以通过重复 $(rand...) 构造相应的次数(或定义一个用户函数来执行此操作)来修改它以每行选择 2 个(或更多)随机单词(有重复项)。

    从每一行中选择 N 单词而不重复(按位置),有点棘手:

    awk '
    BEGIN { N=2; srand() } 
    { 
        #Collect fields into an array (w)
        delete w;
        for(i=1;i<=NF;i++) w[i]=$i; 
    
        #Randomize Array (Fisher–Yates style)
        for(j=NF;j>=2;j--) { 
           r=1+int(rand()*(j));
           if(r!=j) { 
              x=w[j]; w[j]=w[r]; w[r]=x; 
           } 
        }
    
        #Take N first items off the randomized array 
        for(g=1;g<=(N<NF?N:NF);g++) {
           if(g>1) printf " "
           printf w[g];       
        }   
        printf "\n"
    }' data.txt
    

    N - 是每行要选择的(最大)字数。

    要选择每行随机(最多 N)个项目,修改代码如下:

    awk '
    BEGIN { N=2; srand() } 
    { 
        #Collect fields into an array (w)
        delete w;
        for(i=1;i<=NF;i++) w[i]=$i; 
    
        #Randomize Array (Fisher–Yates style)
        for(j=NF;j>=2;j--) { 
           r=1+int(rand()*(j));
           if(r!=j) { 
              x=w[j]; w[j]=w[r]; w[r]=x; 
           } 
        }
    
        #Take L < N first items off the randomized array 
        L=1+int(rand()*N);
        for(g=1;g<=(L<NF?L:NF);g++) {
           if(g>1) printf " "
           printf w[g];       
        }   
        printf "\n"
    }' data.txt
    

    这将在每行打印 1 或 2 (N) 个随机选择的单词。

    这段代码仍然可以稍微优化一下(即只对数组的前 L 个元素进行混洗),但它比基于 shell 的解决方案快 2 或 3 个数量级

    【讨论】:

    • 这是一个很好的答案。你知道我如何随机化它以返回 1-2 个字符串而不仅仅是 1 个字符串吗?
    • @Inian,没关系,但需要我手动更改号码。如果你愿意,你可以留下它。我相信它会帮助寻找类似解决方案的人。
    【解决方案3】:

    尝试 bash

    cat file1  | xargs -n1  -I@ bash -c "output_count=2; \
       line=\$(echo \"@\"); \
       words=\$(echo  \${line} | wc -w); \
       for i in  \$(eval echo \"{1..\${output_count}}\"); do \
          select=\$((1 + RANDOM % \${words})); \
          echo  \${line} | cut -d \" \" -f \${select} | tr '\n' ' '; \
       done;
       echo \" \" "
    

    假设文件名为file1。 为了改变随机选择单词的数量,给output_count设置一个不同的数字

    打印

    $ cat file1  | xargs -n1  -I@ bash -c "output_count=2; \
       line=\$(echo \"@\"); \
       words=\$(echo  \${line} | wc -w); \
       for i in  \$(eval echo \"{1..\${output_count}}\"); do \
          select=\$((1 + RANDOM % \${words})); \
          echo  \${line} | cut -d \" \" -f \${select} | tr '\n' ' '; \
       done;
       echo \" \" "
    #Example #Example
    #Examples #Help
    #Support #Learn
    $ cat file1  | xargs -n1  -I@ bash -c "output_count=2; \
       line=\$(echo \"@\"); \
       words=\$(echo  \${line} | wc -w); \
       for i in  \$(eval echo \"{1..\${output_count}}\"); do \
          select=\$((1 + RANDOM % \${words})); \
          echo  \${line} | cut -d \" \" -f \${select} | tr '\n' ' '; \
       done;
       echo \" \" "
    #Question #StackOverflow
    #Help #Help
    #Everyone #Learn
    

    【讨论】:

    • @DomainsFeatured 如果您不想将同一个单词打印两次,这显然是行不通的。有一些方法可以轻松实现这一目标。例如,将单词保留在一个数组中,并将随机选择的单词与最后一个单词交换,并在每次迭代时缩短数组的长度。如果您需要,请告诉我。
    【解决方案4】:

    这可能对你有用(GNU sed):

    sed 'y/ /\n/;s/.*/echo "&"|shuf -n$((RANDOM%2+1))/e;y/\n/ /' file
    

    用换行符和使用seds替换eflag替换每行中的空格,将每组行传递给shuf -n命令 .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-03
      相关资源
      最近更新 更多