次のファイルがあります( file1 )
その他のファイル 1
<?xml version="1.0" encoding="UTF-8"?>
<apps>
<app name="UAT/ECC/Global/MES/1206/MRP-S23" ear="UAT/ECC/Global/MES/1206/MRP-S23.ear" xml="UAT/ECC/Glal/ME/120/MRP- S23.xml"/>
<app name="OQ/ediedbn/adSFSF/adSFSF-CL" ear="OQ/ebn/aSF/adSF- CL.ear" xml="OQ/ediedbn/adSFSF/adSSF-CL.xml"/>
<app name="OQ/ediedbn/adaEBS/adOrBS-HR-CL" ear="OQ/ediedbn/adOraS/araEBS-HR-CL.ear" xml="OQ/eddbn/aOraEBS/adOEBS- HR-CL.xml"/>
<app name="UAT/CZ/LIMS/T068_01/LIMS-QA-S03" ear="UAT/CZ/LIS/T068_01/LIS-QA-S03.ear" xml="UAT/CZ/LIMS/T068_01/LIMS-QA-S03.xml"/>
.
.
.
以下は、file1で一致させる必要のある行の例です。
その他のファイル 2
OQ-63/ECC/Glal/Interny/Adapter_Services/adOraEBS-NA
OQ-63/ECC/Glal/MES/58,61/ECC-MRP-S20
OQ-63/ECC/Glbal/MES/CZ/adum-CZ-Adapter
OQ-63/EC/Glal/TI/Adaptvices/adTIS
file1のfile2の行を一致させ、バックスラッシュや他の一般的ではない文字を無視するためにPerl oneliner構文への最善のアプローチは何ですか?
これを試しましたがうまくいきません
a="OQ-63/ECC/Glal/Interny/Adapter_Services/adOraEBS-NA"
perl -pe '/(^|\s)\Q$ENV{a}\E(\s|$)/' file1
答え1
試みにいくつかの問題があります。
- perl -pe はすべての行を印刷します。一致しない行を削除するか、-nを使用して明示的に印刷する必要があります。
- 一致する文字列の前には引用符が付いていますが、\ sを確認してください。
- テストのために、file1 と file2 と一致するいくつかの行を表示すると便利です。 :)
だからこれはうまくいきます:
a="UAT/CZ/LIMS/T068_01/LIMS-QA-S03" perl -ne '/"\Q$ENV{a}\E"/ && print' file1
1行ですべての一致を実行するには、次のようにします。
perl -ne 'BEGIN { open(F2, shift); $re=join("|", map {chomp($_); "\"\Q${_}\E\"";} <F2>);} /$re/ && print' file2 file1
答え2
これはXMLです。正規表現はXMLには適していません、働かなければならないようであるが。
その理由は、XMLは状況に敏感ですが、正規表現はそうではないからです。 XML には意味的に同じですが、同じ正規表現と一致しないさまざまな形式の違いがあります。
ただし、「2番目のファイル」エントリのどれも例の最初のファイルと一致しないようです。 XMLの「名前」フィールドと一致させたいと思います。 (可能であれば、「すべての属性と一致」を避ける必要があります)。
#!/usr/bin/perl
use strict;
use warnings;
#dumper is only needed for the 'print Dumper' line below
#for debugging. Both can safely be removed.
use Data::Dumper;
use XML::Twig;
open ( my $match_file, '<', 'file2' ) or die $!;
chomp ( my @matches = <$match_file> );
my %lookup = map { $_ => 1 } @matches;
#or if you want a more pithy one that IMO is a bit harder to understand.
#my %lookup = map { s/[\r\n]+//gr => 1 } <$match_file>;
print Dumper \%lookup;
my $twig = XML::Twig -> new -> parsefile ( 'file2' );
#xpath is XMLs equivalent of regex, but it's
#more suited to node and attribute matching.
foreach my $app ( $twig -> get_xpath ( '//app' ) ) {
$app -> print if $lookup{$app->att('name')};
#Alternatively extract a single field.
print "XML: ", $app -> att('xml'),"\n";
}
ライナーで?正直なところ、あなたが望むならそうではありません。両方一致を読み、検索/印刷します。
ただし、単一要素の場合は、次を選択できます。
a="UAT/CZ/LIMS/T068_01/LIMS-QA-S03" perl -MXML::Twig -e 'XML::Twig -> new ( twig_handlers => { 'app' => sub { $_ -> print if $_ -> att('name') eq $ENV{'a'} } } ) -> parse ( { do {local $/; <> } )'
しかし、正直なところ - 私は一行で魔法をかけるよりも「長い形式」で書くことに固執します。みんなパターンを使用しようとすると、最終的に非効率的なアルゴリズムが使用されます。みんなこれにより、同じライナーにダブルファイルの読み取りとデータ構造があり、混乱しすぎます。