我有一个包含以下文本(file1)的文件 -
1SER CA 1 1.401 0.040 0.887
2GLN CA 2 1.708 -0.155 1.002
3ALA CA 3 1.870 -0.103 0.662
4GLU CA 4 1.829 0.274 0.695
我有一个单独的文件(文件2) -
1MET CA 1 17.704 15.987 17.370
2ARG CA 2 17.811 16.145 17.712
3ARG CA 3 17.634 16.267 18.034
4TYR CA 4 17.465 16.615 18.002
我的目标是用file2的2-4中的数据替换file1中2-4范围内的字符。
期望的输出 -
1MET CA 1 1.401 0.040 0.887
2ARG CA 2 1.708 -0.155 1.002
3ARG CA 3 1.870 -0.103 0.662
4TYR CA 4 1.829 0.274 0.695
即。 file2的2-4中的字符放在file1的字节2-4中。
我知道我可以使用cut -c 2-4 | sed ...
缩小所需区域的范围
但是我无法从单独的文件中“读取”数据并进行替换。
我觉得awk可能更容易,但请不要基于列的答案。它需要是一个基于文件中字符范围的解决方案(在本例中为2-4)。
添加示例
解决方案应该能够做到这一点 - 文件1 -
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
文件2 -
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
输出 -
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
答案 0 :(得分:3)
如果要替换列,只需存储file1中的数据并将其替换为file2:
// These rules give anyone, even people who are not users of your app,
// read and write access to your database
{
"rules": {
".read": true,
".write": true
}
}
您还可以存储两个第一列的值,然后将其替换为#34;手动"如delete a column with awk or sed中所示:
$ awk 'FNR==NR {col1[FNR]=$1; col2[FNR]=$2; next} {$1=col1[FNR]; $2=col2[FNR]}1' f1 f2
1SER CA 1 17.704 15.987 17.370
2GLN CA 2 17.811 16.145 17.712
3ALA CA 3 17.634 16.267 18.034
4GLU CA 4 17.465 16.615 18.002
如果您只想替换某些字符,请使用substr()
提取这些字符:
$ awk 'FNR==NR {data[FNR]=$1 OFS $2; next} {$0=gensub(/(\s*\S+){2}/,data[FNR],1)}1' f1 f2
1SER CA 1 17.704 15.987 17.370
2GLN CA 2 17.811 16.145 17.712
3ALA CA 3 17.634 16.267 18.034
4GLU CA 4 17.465 16.615 18.002
那是:
$ awk -v start=2 -v len=3 'FNR==NR{data[FNR]=substr($0, start, len); next} {$0=substr($0, 1, 2) data[FNR] substr($0, start+len+1)}1' f2 f1
AABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
答案 1 :(得分:2)
如果按“列”和“字节”表示你实际上是指“字符”,那么:
$ cat tst.awk
BEGIN {
split(range,r,/-/)
repS = r[1]
repL = r[2] - r[1] + 1
befL = repS - 1
aftS = repS + repL
}
NR==FNR { rep[NR] = substr($0,repS,repL); next }
{ print substr($0,1,befL) rep[FNR] substr($0,aftS) }
$ awk -v range='2-4' -f tst.awk file2 file1
1MET CA 1 1.401 0.040 0.887
2ARG CA 2 1.708 -0.155 1.002
3ARG CA 3 1.870 -0.103 0.662
4TYR CA 4 1.829 0.274 0.695
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$ awk -v range='10-25' -f tst.awk file2 file1
1SER CA 1 17.704 0.040 0.887
2GLN CA 2 17.811 -0.155 1.002
3ALA CA 3 17.634 -0.103 0.662
4GLU CA 4 17.465 0.274 0.695
AAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAA
AAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAA
AAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAA
以上使用了您的示例的连接作为输入文件。
答案 2 :(得分:2)
paste
和cut
$ paste -d '' <(cut -c1 file1) <(cut -c2-4 file2) <(cut -c5- file1)
1MET CA 1 1.401 0.040 0.887
2ARG CA 2 1.708 -0.155 1.002
3ARG CA 3 1.870 -0.103 0.662
4TYR CA 4 1.829 0.274 0.695
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
ABBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
使用变量:
$ s=10
$ e=25
$ paste -d '' <(cut -c1-$((s-1)) file1) <(cut -c"$s"-"$e" file2) <(cut -c$((e+1))- file1)
1SER CA 1 17.704 0.040 0.887
2GLN CA 2 17.811 -0.155 1.002
3ALA CA 3 17.634 -0.103 0.662
4GLU CA 4 17.465 0.274 0.695
AAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAA
AAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAA
AAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAA
答案 3 :(得分:0)
TXR Lisp中这个过长的单行代码从两个文件中获取两个懒惰的字符串列表,然后以所需的方式将它们合并为一个。 -t
选项将结果值(字符串列表)打印为行。
$ txr -t '[apply mapcar* (ret `@{1 [0]}@{2 [1..4]}@{1 [4..:]}`)
(mapcar [chain open-file get-lines] *args*)]' file1 file2
1MET CA 1 1.401 0.040 0.887
2ARG CA 2 1.708 -0.155 1.002
3ARG CA 3 1.870 -0.103 0.662
4TYR CA 4 1.829 0.274 0.695
原则上,它是一种非常类似的解决方案,使用paste
将多个cut
流组合在一起(感谢Bash命令替换),除了所有流都在一个过程,使用数据结构,并且file1
不会被扫描两次。
变量*args*
引用剩余的命令行参数,作为字符串列表。内部mapcar
通过open-file
和get-lines
的链接将这些字符串映射为文件,并从每个字符串中获取字符串的惰性列表。然后将这两个惰性行列表应用于mapcar*
函数,以通过(ret ...)
生成的匿名函数并行映射其元素。 ret
运算符构造一个匿名函数,其参数隐式派生自正文中出现的@1
和@2
编号参数。内插准字符串用于执行从左和右字符串中选择字符的操作。 @1
会选择整个左侧字符串。支撑语法@{1 [0]}
表示其第一个字符,@{2 [1..4]}
表示切片提取。
mapcar*
函数是mapcar
的惰性版本,这很重要:这可以防止我们在打印之前在内存中构造整个输出。代码对延迟列表的输入进行操作,因此当映射遍历这些列表时进行输入,并且通过-t
选项消耗输出列表来驱动行进。也就是说,表达式立即从mapcar*
中返回一个惰性列表,然后打印出该列表(感谢-t
选项),强制执行该操作延迟列表驱动产生它的映射,这会驱动延迟输入列表的消耗,从而驱动源文件的读取。
我们可以看到ret
表达式的扩展是什么样的:
$ txr -p '(macroexpand (quote (ret `@{1 [0]}@{2 [1..4]}@{1 [4..:]}`)))'
(lambda (#:arg-01-0003
#:arg-02-0004 . #:rest-0002)
[identity (progn #:rest-0002
`@{#:arg-01-0003 [0]}@{#:arg-02-0004 [1..4]}@{#:arg-01-0003 [4..:]}`)])
ret
检查了内容,钻进插值的准字符串以找出&#34;元数&#34;参数。它注意到最高的一个是@2
,因此生成一个双参数函数(带尾随参数的rest参数)。参数生成为临时符号,这些符号替换所有出现的编号变量。
我们可以证明mapcar*
是懒惰的,比如将它乘以两个增加整数的无限列表,然后只从结果中取出前十个方格:
$ txr -p '(take 10 [mapcar* * (range 0) (range 0)])'
(0 1 4 9 16 25 36 49 64 81)
答案 4 :(得分:-1)
你可以给出
{{1}}
命令尝试:将行连接在一起然后切掉有缺陷的列。
join需要对文件进行排序。