我的输入文件如下所示:
#key string pos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12
key2 00A00AAA000AAAA00A 3, 18
我想在每个关键行的末尾添加一个新列(制表符分隔)。如果A
在输入文件的第 2 列中找到 an,则新列将包含输入文件的第 3 列中给出的位置。如果0
在输入文件的第 2 列中找到 a,则不应在新列中打印该位置。
基本上,这是期望的输出:
#key string pos(string) Apos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12 2, 18
key2 00A00AAA000AAAA00A 3, 18 3, 18
简短说明:
(键1)
- 索引 2 处的字符串在新列中添加 了一个
A
-> 项2
- 索引 3 处的字符串有一个
0
-> item3
不是添加到新列 - 索引 12 处的字符串有一个
0
-> 项12
不是添加到新列 - 索引 18 处的字符串在新列中添加了一个
A
-> 项18
我正在 python 中执行此操作,但我陷入了多个键和项目的困境(字符串处理起来很长),所以我想我可以向您寻求命令行(更轻量级)解决方案的建议。
我的想法是:
- 拆分 pos(string) 字段,获取我在字符串字段中搜索的索引
- 获取字符串中给定索引处的字符
- for 语句(?)
答案1
下面的脚本怎么样awk
:
#!/usr/bin/awk -f
BEGIN {
FS="\t"
print "#key\tstring\tpos(string)\tApos(string)"
}
{
out=""
printf "%s\t",$0
split($2,str,"")
gsub(/ /,"",$3)
split($3,pos,",")
for (i in pos){
if (str[pos[i]]=="A"){
out = out pos[i] ", "
}
}
gsub(/, $/,"",out)
print out
}
将其另存为(例如)findA.awk
并使其可执行chmod +x findA.awk
。
然后针对您的输入数据运行它并将输出重定向到一个新文件:
./findA.awk input.txt > output.txt
cat output.txt
#key string pos(string) Apos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12 2, 18
key2 00A00AAA000AAAA00A 3, 18 3, 18
输出不像您的示例那么整洁,因为它是制表符分隔的(根据您的要求),并且制表符宽度与各种字符串的宽度不对齐。
答案2
我不确定你现在是如何做的(查看你的 Python 代码会很有帮助),但你可以创建第 3 列的元素列表,这些元素指向第 2 列中的“A”,如下所示:
[i for i in COLUMN3 if COLUMN2[i]=='A']
这似乎是一个简单的问题,但也许我并不完全理解。也许您忘记了字符串是可迭代的?
答案3
一个可怕的perl
:
$ perl -anle '
printf "%s Apos(string)\n",$_ and next if /^#/;
printf "%s",$_;
$len = 12 - length((split(/\s+/,$_,3))[-1]);
for $pos_ss (@F[2..$#F]) {
$char = substr($F[1],int($pos_ss)-1,1);
push @res, int($pos_ss) if $char eq 'A';
}
printf "%@{[12-4+$len]}s\n", join ", ",@res;
@res=();
' file
#key string pos(string) Apos(string)
key1 AA000AA000000AAA0A 2, 3, 18, 12 2, 18
key2 00A00AAA000AAAA00A 3, 18 3, 18
它的工作原理与我的解决方案类似这个答案,加上添加$len
变量来计算需要打印最后一列对齐的格式。