【问题标题】:How awk the filename as a column in the output?如何将文件名作为输出中的一列?
【发布时间】:2016-03-03 15:12:23
【问题描述】:

我正在尝试在一个目录中的多个文件的内容中执行一些 grep 并将我的 grep 匹配附加到一个文件中,在我的输出中,我还想要一个具有文件名的列以及从哪些文件中了解条目被拾起。我试图用 awk 来做同样的事情,但它没有用。

for i in *_2.5kb.txt; do more $i | grep "NM_001080771" | echo `basename $i` | awk -F'[_.]' '{print $1"_"$2}' | head >> prom_genes_2.5kb.txt; done

文件名是这样的,我有大约 50 个文件

    48hrs_CT_merged_peaks_2.5kb.txt
    48hrs_TAMO_merged_peaks_2.5kb.txt
    72hrs_TAMO_merged_peaks_2.5kb.txt
    72hrs_CT_merged_peaks_2.5kb.txt
    5D_CT_merged_peaks_2.5kb.txt
    5D_TAMO_merged_peaks_2.5kb.txt

每个文件包含几行

chr1    3663275 3663483 14  2.55788 2.99631 1.40767 NM_001011874    -
chr1    4481687 4488063 264 7.85098 28.25170    26.41094    NM_011441   -
chr1    5008006 5013929 243 8.20677 26.17854    24.37907    NM_021374   -
chr1    5578362 5579949 65  3.48568 7.83501 6.57570 NM_011011   +
chr1    5905702 5908002 148 5.84647 16.53171    14.88463    NM_010342   -
chr1    9288507 9290352 77  4.04459 9.12442 7.77642 NM_027671   -
chr1    9291742 9292528 142 5.74749 16.21792    14.28185    NM_027671   -
chr1    9535689 9536176 72  4.45286 8.82567 7.29563 NM_021511   +
chr1    9535689 9536176 72  4.45286 8.82567 7.29563 NM_175236   +
chr1    9535689 9536176 72  4.45286 8.82567 7.29563 NR_027664   +

当我得到"NM_001080771" 的匹配项时,我将该行的全部内容打印到一个新文件中,并且对于每个文件,此操作都在完成,并将匹配项附加到一个输出文件中。我还想在最终输出中添加一个带有文件名的列,如上所示,以便我知道从哪个文件中获取条目。

想要的输出

chr4    21610972    21618492    193 7.28409 21.01724    19.35525    NM_001080771    -   48hrs_CT
chr4    21605096    21618696    76  4.22442 9.32981 7.68131 NM_001080771    -   48hrs_TAMO
chr4    21604864    21618713    12  1.78194 2.36793 1.25883 NM_001080771    -   72hrs_CT
chr4    21610305    21615717    26  2.90579 4.47333 2.65353 NM_001080771    -   72hrs_TAMO
chr4    21609924    21618600    23  2.63778 4.0642  2.33685 NM_001080771    -   5D_CT
chr4    21609936    21618680    30  5.63778 3.0642  8.33685 NM_001080771    -   5D_TAMO

这不起作用。我想基本上附加一个列,其中文件名也应该作为条目添加到第一列或最后一列。该怎么做?

【问题讨论】:

  • 您需要向我们展示您的输入和所需输出的样本,否则我们很难为您提供帮助。
  • @TomFenech 我已经修改了问题

标签: awk sed grep


【解决方案1】:

或者你可以在awk做所有事情

 awk '/NM_001080771/ {print $0, FILENAME}' *_2.5kb.txt

这会将文件名修剪成所需的格式

$ awk '/NM_001080771/{sub(/_merged_peaks_2.5kb.txt/,"",FILENAME); 
                      print $0, FILENAME}' *_2.5kb.txt

【讨论】:

  • 适用于当前的文件数量,但是是打印整个文件名,我只是想添加名称的子集,如48hrs_TAMO。有点服务于目的。我现在可以用它。谢谢大家。由于这不是确切的答案,我不接受它作为答案。可以吗?
  • 没关系,但是您检查了删除后缀的第二个脚本吗?
  • 是的,很抱歉,第二个也完全正常。是的,我现在接受。非常感谢。我已经放入了一个基于脚本的操作,以便该操作也可以在大量文件中使用。非常感谢。
  • @vchris_ngs 这是您问题的正确答案。
  • 直到*_2.5kb.txt 膨胀到你的shell 无法处理(/usr/bin/awk: Argument list too long.),即...
【解决方案2】:

只要文件数量不大,何乐而不为:

grep NM_001080771 *_2.5kb.txt | awk -F: '{print $2,$1}'

如果您有太多文件无法使用,这是一种基于脚本的方法,它使用 awk 附加文件名:

#!/bin/sh
for i in *_2.5kb.txt; do
    < $i grep "NM_001080771" | \
        awk -v where=`basename $i` '{print $0,where}'
done

./thatscript | head > prom_genes_2.5kb.txt

这里我们使用 awk 的-v VAR=VALUE 命令行功能来传递文件名(因为我们使用的是标准输入,所以在 awk 的内置 FILENAME 变量中没有任何有用的东西)。 p>

您还可以围绕@karakfa 的优雅 awk-only 方法使用这样的循环:

#!/bin/sh
for i in *_2.5kb.txt; do
    awk '/NM_001080771/ {print $0, FILENAME}' $i
done

最后,这是一个带有所需文件名的版本:

#!/bin/sh
for i in *_2.5kb.txt; do
      awk -v TAG=${i%_merged_peaks_2.5kb.txt} '/NM_001080771/ {print $0, TAG}' $i
done

(这使用 shell 的变量替换 ${variable%pattern}variable 的末尾修剪 pattern

奖金

猜你以后可能想搜索其他字符串,那我们为什么不像这样传入搜索字符串:

#!/bin/sh
what=${1?Need search string}
for i in *_2.5kb.txt; do
  awk -v TAG=${i%_merged_peaks_2.5kb.txt} /${what}/' {print $0, TAG}' $i
done

./thatscript NM_001080771 | head > prom_genes_2.5kb.txt

另一个编辑

或者,如果您有病态的需要过度复杂化和迂腐引用事物,即使是在 5 行“一次性”脚本中:

#!/bin/sh
shopt -s nullglob

what="${1?Need search string}"
filematch="*_2.5kb.txt"
trimsuffix="_merged_peaks_2.5kb.txt"

for filename in $filematch; do
    awk -v tag="${filename%${trimsuffix}}" \
        -v what="${what}" \
        '$0 ~ what {print $0, tag}' $filename
done

【讨论】:

  • shell 脚本工作正常,因为我有大约 50 个文件,但我想稍后也使用它,让我们说一个目录中有 1k 个文件。唯一的事情是它打印了我正在寻找的文件名的一部分的整个文件名
  • @vchris_ngs 好的,最后一个例子包括你想要的文件名。
  • 对不起,两个答案都适用,但我不能同时接受,但 karakfa 的第二个答案也适用,所以如果约翰也能接受。看来我无权同时接受这两个答案。
  • 以上是错误的方法,因此会很慢而且有问题。永远不要仅仅为了操作文本而编写 shell 循环。总是引用你的 shell 变量。不要使用已弃用的反引号。永远不要让 shell 变量扩展成为 awk 脚本的一部分。不要在 awk 中使用全大写的变量名。
猜你喜欢
  • 2013-03-28
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
相关资源
最近更新 更多