使用sed从大文本文件中提取多行,同时保留每个尾随换行符(Bash脚本)

时间:2016-07-06 15:17:42

标签: bash shell awk sed large-files

我有一个数百万行的大文本文件,我需要提取特定的行。

由于我需要提取大约300000行(要从文件中读取要提取的行号),我会按批处理x行(比如200)处理它们,以使用以下命令加速处理:

sed '1000p;1002p;2003p;...(200 times)...10001q;d' large_text_file >> extracted.txt

首先我构造字符串1000p;1002p;2003p;...(200 times)...10001q;d,然后用字符串作为参数调用sed命令并重复此操作直到处理完所有行。

 sed_lines="1000p;1002p;2003p;...(200 times)...10001q;d"
 sed "$sed_lines" large_text_file >> extracted.txt

我遇到的问题是,这200行现在被视为一行,因为sed不会将\n保留在每行的末尾。

问题1 :sed中是否有选项可以保留每行末尾的\ n?

回答1 :好的,我写这篇文章后很快就想到了这个。基本上我错过了行中$sentences左右的双引号:

echo $sentences >> $forig.pseudo ==> echo "$sentences" >> $forig.pseudo

问题2:有更快的方法吗?

回答2 :fedorqui对awk的回答非常快速有效

为了便于理解,以下是执行此过程的大部分脚本(使用fedorqui关于while的评论编辑):

echo "Extracting lines"
sed_lines=""
while IFS=$'\t' read -r linenr rest; do
        sed_lines+="$linenr"                   # Append line number
        ((cnt++))                              # Batch counter
        if [ "$cnt" -eq 200 ]; then
                sed_lines+="q;d"               
                sentences=$(sed "$sed_lines" $forig)   # Extract lines from file
                ((thres_cnt+=100))
                echo "$thres_cnt lines processed"
                echo $sentences >> $forig.pseudo       # Write lines to new file
                sed_lines=""
                cnt=0
        else
                sed_lines+="p;"
        fi
done < "$fperp"_cut_sorted

1 个答案:

答案 0 :(得分:3)

如何使用awk呢?首先将行号存储在一个数组中,然后继续检查该文件的行号是否在该数组中:

awk 'FNR==NR{line[$0]=$0; next} FNR in line' line_numbers file

示例

$ cat line_numbers
8
16
4
6
9
$ cat file
1 hello
2 hello
3 hello
4 hello
5 hello
6 hello
7 hello
8 hello
9 hello
10 hello
11 hello
12 hello
13 hello
14 hello
15 hello
16 hello
17 hello
18 hello
19 hello
20 hello
$ awk 'FNR==NR{line[$0]=$0; next} FNR in line' line_numbers file 
4 hello
6 hello
8 hello
9 hello
16 hello