使用 awk 打印自定义行

Use awk to print custom lines

我有这样一个文件:

>ref
AAAAAAA
>seq1
BBBBBBB
>seq2
CCCCCCC
>seq3
DDDDDD

我想得到:

>ref
AAAAAAA
>seq1
BBBBBBB
>ref
AAAAAAA
>seq2
CCCCCCC
>ref
AAAAAAA
>seq3
DDDDDD

我想在 bash 中使用这个命令:

ref=$(head -n 2 file)
awk '/>/{print "'"$ref"'"}1' file

这是我得到的:

awk: non-terminated string >ref... at source line 2
 context is
    />/{print ">ref >>> 
 <<< 

知道发生了什么事吗? :) 非常感谢!


编辑:我想将此管道用于许多文件,所有这些文件都以不同的 ref 开头:ref1 用于 file1ref2 用于 file2,.. . 因此考虑使用 head 将每个 ref 存储在一个变量中以用于每个文件:)

问题

问题是当 ref 具有值

>ref
AAAAAA

你的 awk 调用

awk '/>/{print "'"$ref"'"}1' file

最终成为

awk '/>/{print ">ref
AAAAAA"}1' file

shell 扩展后。 awk 不允许在字符串文字中换行,所以这会爆炸。如果您文件的前两行是

>ref"
print "AAAAA

它会起作用(除了顶部会有绒毛),但这并不能帮助我们找到一个合理的解决方案。

awk 中的解决方案

用 awk 解决这个问题的一种方法是 assemble ref 在 awk 本身:

awk 'NR <= 2 { ref = ref [=14=] ORS; next } />/ { [=14=] = ref [=14=] } 1' filename

也就是

NR <= 2 {                # First two lines:
  ref = ref [=15=] ORS       # build ref string (ORS is "\n" by default)
  next                   # and stop there
}
/>/ {                    # after that: For lines that contain a >
  [=15=] = ref [=15=]            # prepend ref
}
1                        # then print

sed 中的解决方案

其实我更喜欢 sed 这个:

sed '1h; 2H; 1,2d; />/{ x; p; x; }' filename

即:

1h                # first line: save to hold buffer
2H                # second line: append to hold buffer
1,2d              # first two lines: stop here
/>/ {             # after that: If line contains >
  x               # swap hold buffer, pattern space
  p               # print what used to be in the hold buffer (the first
                  # two lines that we saved above)
  x               # swap back
}
                  # when we drop off the end, the original line will be
                  # printed.