区切り文字なしで2つのファイルの特定の場所を比較する方法

区切り文字なしで2つのファイルの特定の場所を比較する方法

2つのファイルを1行ずつ比較する必要があります。私は他の行だけを出力したいのですが、違いを判断するときは、文字4-6と10-12は無視する必要があります。特定のフィールド区切り記号などはありません。

例:

  • ファイル1
    abc123def999
    ghi456klm999
    nop789qrs999
    
  • ファイル2
    abc000def000
    xxx000yyy000
    nop000qrs000
    

この例では、2番目の行だけが異なる必要があります。

readファイルには何百万ものレコードがあるため、ループがファイルを1行ずつ解析することは望ましくありません。

答え1

GNU awkをFIELDWIDTHSパラメータとして使用する:

$ paste file[12] |
    awk -v FIELDWIDTHS='3 3 3 3 1 3 3 3 3' '$1!=$6 || $3!=$8'
ghi456klm999    xxx000yyy000

pasteここでは、2つのファイルを並べて貼り付けるコマンドを使用します。次に、awkのFIELDWIDTHSパラメーターを使用してフィールド長を定義するため、2つのファイルの行が固定長であると仮定し、ここで関連フィールドの違いを比較します。一行ずつ行われます。

または、すべてのシェルで awk を使用します。

$ paste file[12] |
    awk 'function key(s){return substr(s,1,3) substr(s,7,3)} key($1) != key($2)'
ghi456klm999    xxx000yyy000

答え2

予想される出力を示しておらず、要件が何であるかを実際に知らせていないので、以下はすべてのUnixシステムのすべてのシェルでawkを使用して必要なものを推測します.

$ cat tst.awk
{ key = substr($0,1,3) substr($0,7,3) }
NR == FNR {
    a[key]
    next
}
!(key in a)

$ awk -f tst.awk file1 file2
xxx000yyy000

$ awk -f tst.awk file2 file1
ghi456klm999

答え3

どちらのファイルにも「何百万ものレコード」がありますか?短いファイルを選択し、各行を読み、「^(行の先頭)で$始まり、」(行の終わり)で終わる正規表現を生成します。検索文字列はその間にあります。無視する位置を「.」(正規表現「すべての単一文字に一致」)に設定します。例えば" ^abc...def...$"。一時ファイル(file1.tmp)に保存します(何百万?)。すべての行を処理すると、inはgrep -E -f file1.tmp file2正規表現を検索します。file1.tmpfile2

答え4

方法1)perl

このunpack機能は、Perl環境トレイに提供されている形式に基づいて特定の範囲の文字を抽出するため、この状況に最適です。(A3x3)2A*=> 3つのASCII文字を選択し、3つの文字をスキップします。このプロセスをもう一度繰り返して、残りのものを取得します。

fmt='(A3x3)2A*' \
perl -nse 'print if "@{[unpack($ENV{fmt})]}" ne
"@{[unpack($ENV{fmt},scalar(<STDIN>))]}";
' -- -\"= File1 < File2
ghi456klm999

方法-2)paste+GNU sed

貼り付けは、2つのファイルの対応する行をタブで区切って並べて配置します。したがって、ファイルにタブがあってはならないとします。次に、2つのファイルのデータで、4-6文字と10-12文字を同じ文字「.」に置き換えます。行を比較する前にInesが一致しない場合は、file1行を印刷します。

# helper vars aid in writing sed code
x3='...'
A3="($x3)"
A3x3=$A3$x3
srch="^$A3x3$A3x3"
repl="\\1$x3\\2$x3"

paste File1 File2 |
sed -En 'y/\t/\n/;h
  '"s/$srch/$repl/Mg"'
  /^(.*)\n\1$/d;g;P
' -

方法-3)Python

組み込みのzip機能は、2つのファイルの行を並べて表示します。

python3 -c 'import sys
# skip chars: 4-6 10-12
AoT = [(0,3),(6,9),(12,None)] # array of tuples

fx = lambda t: \
  a[t[0]:t[1]] != b[t[0]:t[1]]

ifile1,ifile2 = sys.argv[1:]
with open(ifile1) as f1,\
     open(ifile2) as f2:
  for a,b in zip(f1,f2):
    if any(map(fx,AoT)):
      print(a,end="")
' File1 File2

関連情報