1

我有以下格式的文本文件:

variableStep chrom=chr1 span=10
10161   1
10171   1
10181   2
10191   2
10201   2
10211   2
10221   2
10231   2
10241   2
10251   1
variableStep chrom=chr10 span=10
70711   1
70721   2
70731   2
70741   2
70751   2
70761   2
70771   2
70781   2
70791   1
71161   1
71171   1
71181   1
variableStep chrom=chr11 span=10
104731  1
104741  1
104751  1
104761  1
104771  1
104781  1
104791  1
104801  1
128711  1
128721  1
128731  1

我需要一种方法将其分解为多个文件,例如“chr1.txt”、“chr10.txt”和“chr11.txt”。我该怎么做呢?

我关于以下方式:

cat file.txt | \
while IFS=$'\t' read  -r -a rowArray; do
    echo -e "${rowArray[0]}\t${rowArray[1]}\t${rowArray[2]}"
done > $file.mod.txt

逐行读取,然后逐行保存。但是,我需要一些更精细的跨越行的东西。“chr1.txt”将包括从第 10161 1 行到第 10251 1 行的所有内容,“chr10.txt”将包括从第 70711 1 行到第 71181 1 行的所有内容,等等。这也是具体的,我必须阅读实际chr# 也从每一行,并将其保存为文件名。

非常感谢您的帮助。

4

4 回答 4

4
awk -F'[ =]' '
  $1 == "variableStep" {file = $3 ".txt"; next}
  file != "" {print > file}' < input.txt
于 2013-06-12T21:56:11.533 回答
1

这对我有用:

IFS=$'\n'
curfile=""
content=($(< file.txt))
for ((idx = 0; idx < ${#content[@]}; idx++)); do
    if [[ ${content[idx]} =~ ^.*chrom=(\\b.*?\\b)\ .*$ ]]; then
        curfile="${BASH_REMATCH[1]}.txt"
        rm -rf ${curfile}
    elif [ -n "${curfile}" ]; then
        echo ${content[idx]} >> ${curfile}
    fi
done
于 2013-06-12T16:50:13.153 回答
1

awk 适用于这个问题域,因为文本文件已经(或多或少)组织成列。这是我会使用的:

awk 'NF == 3 && index($2, "=") { filename = substr($2, index($2, "=") + 1) }
     NF == 2 && filename { print $0 > (filename ".txt") }' < input.txt

解释:

将variableStep开头的行视为“三列”,将其他行视为“两列”。上面的脚本说,“逐行解析文本文件;如果一行有三列,而第二列包含'='字符,则分配'第二列中出现在'='之后的所有字符字符'到一个名为filename.filename

笔记:

  • NF是 Awk 中的一个内置变量,表示“字段数”,其中“字段”(在这种情况下)可以被认为是一列数据。
  • $0$2是内置变量,分别代表整行和第二列数据。($1代表第一列,$3代表第三列,等等...)
  • substrindex是此处描述的内置函数:http : //www.gnu.org/software/gawk/manual/gawk.html#String-Functions 重定向运算符 (>)在 Awk 中的作用与在 shell 中的作用不同脚本; 随后对同一文件的写入将被附加。
  • 字符串连接只需通过将表达式彼此相邻地编写来执行。括号确保连接发生在文件被写入之前。

更多细节可以在这里找到:http ://www.gnu.org/software/gawk/manual/gawk.html#Two-Rules

于 2013-06-12T23:42:26.177 回答
-1

我用 sed 过滤....

代码部分:

改善 ~/so_test $ cat zsplit.sh

cntr=1;
prev=1;
for curr in `cat ztmpfile2.txt | nl | grep variableStep | tr -s " " | cut -d" " -f2 | sed -n 's/variableStep//p'`
do
sed -n "$prev,$(( ${curr} - 1))p" ztmpfile2.txt > zchap$cntr.txt ;
#echo "displaying : : zchap$cntr.txt " ;
#cat zchap$cntr.txt ;
prev=$curr; cntr=$(( $cntr + 1 ));
done

 sed -n "$prev,$ p" ztmpfile2.txt > zchap$cntr.txt ;
 #echo "displaying : : zchap$cntr.txt " ;
 #cat zchap$cntr.txt ;

输出 :

Kaizen ~/so_test $  ./zsplit.sh
+ ./zsplit.sh
zchap1.txt :: 1 :: 1
displaying : : zchap1.txt
variableStep chrom=chr1 span=10
zchap2.txt :: 1 :: 12
displaying : : zchap2.txt
variableStep chrom=chr1 span=10
10161   1
10171   1
10181   2
10191   2
10201   2
10211   2
10221   2
10231   2
10241   2
10251   1
zchap3.txt :: 12 :: 25
displaying : : zchap3.txt
 variableStep chrom=chr10 span=10
70711   1
70721   2
70731   2
70741   2
70751   2
70761   2
70771   2
70781   2
70791   1
71161   1
71171   1
71181   1
displaying : : zchap4.txt
variableStep chrom=chr11 span=10
104731  1
104741  1
104751  1
104761  1
104771  1
104781  1
104791  1
104801  1
128711  1
128721  1
128731  1

从结果 zchap* 文件中,如果您希望可以删除该行: variableStep chrom=chr11 span=10 使用 sed --sed -i '/variableStep/d' zchap*

这有帮助吗?

于 2013-06-12T17:09:12.300 回答