假设文本文件(file1
)包含 m 字母字符串行 S ( S_1 , S_2 ,..., S_m )。每个 S 前面都有一个简短的字母数字字符串作为条形码(此处: foo1 , bar7 , baz3 )。字母串 S 的长度都相同。每个 S 及其前面的条形码由空格分隔。
$ cat file1
foo1 abcdefghijklmnopqrstuvwxyz
bar7 abcdefghijklmnopqrstuvwxyz
baz3 abcdefghijklmnopqrstuvwxyz
假设第二个文件(file2
)包含 n 列范围 R 的规范( R_1 , R_2 ,..., R_n )。列范围在一行上并由空格分隔。每个 R_x 小于 S 。范围的组合长度(即 R_1 + R_2 + ... + R_n )也小于 S 。没有范围重叠或构成彼此的子集。
$ cat file2
2-11 14-19 23-24
关注this excellent answer,我了解我可以通过以下 awk提取所有 S 的第一个范围(即 R_1 )命令,同时保持条形码正确分配:
awk 'NR==FNR{start=$1;lgth=$2;next} {print $1, substr($2,start,lgth)}' FS='-' file2 FS=' ' file1
但是,我不确定如何扩展 awk -code以遍历所有其他范围(此处: R_2 和 R_3 )和将每个追加到不断增长的矩阵中。
$ sought_outcome
foo1 bcdefghijknopqrswx
bar7 bcdefghijknopqrswx
baz3 bcdefghijknopqrswx
修改 为了更好地理解,这里所示的搜索输出使得连接点由空格强调:
2-11 14-19 23-24
foo1 bcdefghijk nopqrs wx
bar7 bcdefghijk nopqrs wx
baz3 bcdefghijk nopqrs wx
答案 0 :(得分:1)
awk
救援!没有任何验证检查!
$ awk 'NR==FNR {printf "%s", "key";
for(i=1;i<=NF;i++)
{split($i,x,"-");
start[i]=x[1];
end[i] =x[2];
printf "%s", FS $i};
print "";
next}
{printf "%s", $1;
for(i in start) printf "%s", FS substr($2,start[i],end[i]-start[i]+1);
print ""}' range file |
column -t
key 2-11 14-19 23-24
foo1 bcdefghijk nopqrs wx
bar7 bcdefghijk nopqrs wx
baz3 bcdefghijk nopqrs wx
或者,没有标题和分裂
$ awk 'NR==FNR{for(i=1;i<=NF;i++)
{split($i,x,"-"); start[i]=x[1]; end[i]=x[2]};
print ""; n=NF; next}
{printf "%s", $1 FS;
for(i=1;i<=n;i++) printf "%s", substr($2,start[i],end[i]-start[i]+1); print ""}' range file column -t
foo1 bcdefghijknopqrswx
bar7 bcdefghijknopqrswx
baz3 bcdefghijknopqrswx
<强>更新强> 但是,剪切/粘贴可能更容易
$ paste -d' ' <(cut -d' ' -f1 file) <(cut -d' ' -f2 file | cut -c$(tr ' ' ',' <range))
foo1 bcdefghijknopqrswx
bar7 bcdefghijknopqrswx
baz3 bcdefghijknopqrswx
答案 1 :(得分:0)
我提出的结果几乎与@karakfas第二个脚本完全相同,但我发现他格式化代码的方式极难阅读,所以我想我还是会发布这个:
$ cat tst.awk
NR==FNR {
for (i=1; i<=NF; i++) {
split($i,range,/-/)
beg[i] = range[1]
end[i] = range[2]
}
numRanges = NF
next
}
{
printf "%s%s", $1, OFS
for (i=1; i<=numRanges; i++) {
printf "%s", substr($2,beg[i],(end[i]-beg[i])+1)
}
print ""
}
$ awk -f tst.awk file2 file1
foo1 bcdefghijknopqrswx
bar7 bcdefghijknopqrswx
baz3 bcdefghijknopqrswx