awk-从一个文件中随机抽取一行,并将其与另一个文件的行组合,输出到第三个文件



在下面的问题中,如果我只是在outfile中写入一个固定字符串,但如果我想使用file1中的随机行而不是固定字符串,那么我就卡住了。我不知道如何将获得随机行的awk代码插入到编辑file2的代码中(或者做同样工作的等效方法(。

文件1:

string1_^%"$"£xxXF%
string2-$^^!dV"$&"}
string3~£""!&vhTT[@
string4_%^c!}[&(SR#
string5_$%&<[*^"!"H
string6_$$£<[*~)!£H

文件2:

@ data1 line1, unique text follows
data1 line2, unique text follows
@ data2 line1, unique text follows
data2 line2, unique text follows
@ data3 line1, unique text follows
data3 line2, unique text follows
@ data4 line1, unique text follows
data4 line2, unique text follows

期望输出:

outfile:

$ data1 line1, unique text follows
data1 line2, unique text follows
fixed_text_inserted
string2-$^^!dV"$&"}
$ data2 line1, unique text follows
data2 line2, unique text follows
fixed_text_inserted
string6_$$£<[*~)!£H
$ data3 line1, unique text follows
data3 line2, unique text follows
fixed_text_inserted
string3~£""!&vhTT[@
$ data4 line1, unique text follows
data4 line2, unique text follows
fixed_text_inserted
string6_$$£<[*~)!£H

fixed_text_inserted总是一样的,只是一个字符串(没有空格或制表符(

每条记录的最后一行(即第4行(是文件1中的一行(这些行包含特殊字符,例如$£%"'%^和文本,但没有空格或制表符(

随机选择是替换,如在我的示例outfile中,其中字符串6_$$£<[*~(!£H}恰好被选中不止一次。

我有大约400个file2,每个都很大(~1GB(,所以我很容易写一个太慢的脚本,但我在用awk实现这一点时遇到了问题。

以下是两个awk命令的想法,每个命令几乎都能完成我想要的一半:

首先从file1:中获取一个随机行

awk 'BEGIN{srand();} {a[NR]=$0} END{for(i=1; i<=5000; i++){x=int(rand()*NR) + 1}}' file 1

然后在从file2:创建新文件(outfile(时使用该随机行

awk 'BEGIN {getline rlines; RS = "#" ; FS = "n"} NR > 1 {print $1"n"$2"n"; printf rlines[NR]; printf "n"}' file2 > outfile

我怀疑将这两条线合并是否是实现这一目标的方法;这些awk线只是给我一个想法(我希望(我正在努力做什么。

我之所以发布这篇文章,不仅是因为我被卡住了,还因为这个问题涉及到如何在awk中处理多个文件以及如何在其中定义复杂变量的一般问题。网上有一些例子,但它们分别对待这些事情。

感谢任何有建议的人,我还没有"糟糕的想法"的感觉。

这将从file1中随机选择一行插入到file2的第三个位置。这对于这项任务来说应该非常快。

$ sed "3i$(shuf -n1 file1)" file2 > file3

如果要每隔三行插入一行,并可能重复随机行,还可以修剪非字母数字边界处的随机字符串。对于多个输入文件重复相同的操作,这应该…

$ awk 'BEGIN   {srand()}
NR==FNR {sub(/[^[:alnum:]].*/,""); a[NR]=$0; size++; next}
FNR==1  {close(f); f=FILENAME".outfile"} 
{print > f} 
!(FNR%2){print a[int(rand()*size)+1] > f}' randomvals file1 file3 ...

首先提供随机值文件,然后提供要更新的文件。将为每个输入文件创建"更新"的附加版本。

听起来可以归结为用第二个文件中的随机行替换一个文件的每三行。使用awkshuf:的组合很容易做到这一点

$ cat file1.txt
#a
b
c
#d
e
f
#g
h
i
$ cat file2.txt
1
2
3
4
5
6
$ awk 'NR == FNR { lines[NR]=$0; next }
{ if (FNR % 3) print; else print lines[++i] }' <(shuf file2.txt) file1.txt
#a
b
6
#d
e
2
#g
h
1

将替换行文件的混洗版本读取到数组中,然后对记录文件的每三行打印一行替换行,而不是原始行。


为了好玩,一个bash等价物使用一个协处理器来访问混洗的文件,而不是将它们存储在数组中。

#!/usr/bin/env bash
# replace.sh originalfile replacementlinesfile
coproc shuf { shuf "$2"; read; }
declare -i i=1
while IFS= read -r line; do
if [ $((i++ % 3)) -eq 0 ]; then
IFS= read -r -u "${shuf[0]}" line
fi
echo "$line"
done < "$1"
echo "done" >&"${shuf[1]}"
wait "$shuf_PID"

相关内容

最新更新