如何在文件中随机选择同一行的字符串

时间:2017-10-23 17:18:11

标签: linux bash random sed cut

我已阅读此帖子Select random lines from a file in bashRandom selection of columns using linux command但是它们并不专门针对需要保持相同顺序的一组行。我还搜索了使用cut命令查找是否有任何随机化选项。

我的尝试:

我正在尝试用新行替换空格,然后对Random进行排序,然后使用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

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

4 个答案:

答案 0 :(得分:3)

这是解决方案

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

答案 1 :(得分:2)

使用AWK:

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

#Question
#Help
#Support

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

从每行重复(按位置)选择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 数量级

答案 2 :(得分:0)

尝试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

答案 3 :(得分:0)

这可能适合你(GNU sed):

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

用换行符替换每行中的空格并使用seds替换e标志,将每组行传递给shuf -n命令 。