2つの文字列が最初に表示される間のファイル部分をすばやく抽出します。

2つの文字列が最初に表示される間のファイル部分をすばやく抽出します。

1行の大容量(MB)テキストファイルがあり、string1とstring2の最初の項目の間の部分を抽出する必要があります。私は多くのレシピを見つけましたが、ほとんどは別の行で作業するか、2番目の文字列の最後の項目まで抽出します。 infile、outfile、string1、string2パラメータを使用して機能することを私が見つけたものは次のとおりです。

#!/bin/bash

a="$(cat $1)"                   ## copy file1 to a

a="$(echo "${a#*"$3"}")"        ## cut up to (including) str1  

echo "${a%%"$4"*}" > $2         ## part after str1 up to str2

## where the last line may also be

printf '%s' "${a%%"$4"*}" > $2  ## part after str1 up to str2

ただし、どちらのバージョンも非常に遅いです(各ファイルに対して複数回繰り返す必要があります)。スピードを上げる方法?

答え1

OPとのチャット中に、いくつかの議論では、1行がWebクエリのJSONであることがわかりました。jq . < input_fileまたは、同じツールを使用してこのファイルをきれいに印刷するpython -mjson.tool input_fileと、ファイルは既存の1行ずつ処理に適しています。

さらなる議論により、これはフラットファイルを生成するための書誌照会であることが明らかになりました。jqOPは、次のプログラム(私の最初のプログラム)が十分に速いと思います。

#!/bin/bash                                                                                                                           

jq -r  < "$1" '.response.docs[] |                                                                                          
    ("    Title: "+.title[]),                                                                                                          
    ("   Authors: "+(.author|join(""))),                                                                                               
    ("    Bibcode: "+.bibcode),                                                                                                        
    ("   AltBibcode: "+(.alternate_bibcode//[] | join(" : "))),                                                                        
    ("  "+(.abstract//"NOABSTRACT")),                                                                                                  
    ""' | fmt | sed 's/^    \?//'

いくつかの微妙な点があります。私たちが望むのは、長い行ではなく要約を包み込み、出力を経由して送信されることですfmt。このプログラムには次の属性があります。別のインデントで始まる行いいえ一緒に組み合わせて、「タイトル:」などのテキストに4/3/4/3/2間隔パターンを追加します。その後、fmtは実際に2つのスペースに要約をインデントしてラップします。次に、sedを使用して他のヘッダー行から3〜4個のスペースを削除します。完璧ではなく、長い著者のリストも圧縮できます。より良いsedプログラムは、作成者を行に再接続し、空のAltBibcodeエントリを削除するなどの操作を実行できます。

出力形式は、awk 1行スクリプトを介して後処理するように慎重に設計されています。

awk -vRS='' -vORS=$'\n\n' !/NOABSTRACT/'

要約せずにアイテムを削除します。

答え2

$ sed -e 's/stringA/\n/;s/.*\n//;s/stringB.*//' file 

stringAより前のコードの削除は、「stringAより前のすべてのエントリを削除」というより明確な方法ではなく、2つのステップ(stringAを改行文字に変更してから最初の行を削除)で行われます。最初最後の文字列の代わりにstringAが発生します。他の多くのツール(PythonやPerlなど)とは異なり、sedは貪欲ではない正規表現をサポートしていません。

$ perl -lpe '
    my($sa, $sb) = qw/stringA stringB/;
    my $p2 = index($_, $sb);
    my $p1 = index($_, $sa)+length($sa);
    $_ = substr($_, $p1, $p2-$p1);
'  file

関連情報