在bash中分解文本文件

时间:2013-06-12 16:26:03

标签: regex linux bash unix io

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

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 个答案:

答案 0 :(得分:4)

awk -F'[ =]' '
  $1 == "variableStep" {file = $3 ".txt"; next}
  file != "" {print > file}' < input.txt

答案 1 :(得分: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

答案 2 :(得分: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变量,则将整行写入通过将filename变量中的字符串与'.txt连接而构造的文件“”。

注意:

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

可在此处找到更多详细信息:http://www.gnu.org/software/gawk/manual/gawk.html#Two-Rules

答案 3 :(得分:-1)

我使用sed过滤....

代码部分:

Kaizen~ / 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 *文件,iff你想要你可以删除行:variableStep chrom = chr11 span = 10使用sed - sed -i '/variableStep/d' zchap*

这有帮助吗?