Linux bashツールで次の文字列を抽出したいと思います。
XXAAGGHH (XXXXX) ERRTYTUUUI
AAAAAAAA ( %%))XX) $@@$&%^&&
AADDDDD$ (.SD F@* @) *$%^^&^&&&
AA^@%%^^ ()[))DS((]) RTTYUU
抽出された解像度は次のようになります。
XXXXX
%%))XX
.SD F@* @
)[))DS((]
残念ながら、文字列の長さが固定されていないため、substrは使用できません。括弧内に括弧(バランスが合わない可能性があります)、スペースまたはタブがあります(実際にはUTF-8横説説ですが、ローカルシステムはASCIIのみを表示できます)。
私が使用するパターンは、「(」:スペース+左角かっこは左境界を表します。)):スペース+右角括弧は右境界を表します。
awk、sed、grepを試しましたが失敗しました。
ヒントをいただけますか?ありがとうございます。
答え1
sed
唯一の解決策:
sed 's/.* (\(.*\)) .*/\1/g'
例:
sed 's/.* (\(.*\)) .*/\1/g' myInput.txt
XXXXX
%%))XX
.SD F@* @
)[))DS((]
答え2
grep -Eo '\(.+\)' input | sed 's/^.//; s/.$//'
答え3
パターンを見つけるために単に例を繰り返すことがソリューションを開発する簡単な方法であることに注意してください。私がよくやっていることです。これにより、他の人がファイルを生成せずにコンソールで試すことができます。
Gawkの唯一のソリューション:
echo 'XXAAGGHH (XXXXX) ERRTYTUUUI
AAAAAAAA ( %%))XX) $@@$&%^&&
AADDDDD$ (.SD F@* @) *$%^^&^&&&
AA^@%%^^ ()[))DS((]) RTTYUU' | gawk '{r=gensub(/^[^(]*\((.*)\)[^)]*$/,"\\1","g",$0);print r}'
XXXXX
%%))XX
.SD F@* @
)[))DS((]
awk専用ソリューション:
echo 'XXAAGGHH (XXXXX) ERRTYTUUUI
AAAAAAAA ( %%))XX) $@@$&%^&&
AADDDDD$ (.SD F@* @) *$%^^&^&&&
AA^@%%^^ ()[))DS((]) RTTYUU' | awk '{gsub(/^[^(]*\(|\)[^)]*$/,"",$0);print $0}'
XXXXX
%%))XX
.SD F@* @
)[))DS((]
sed専用ソリューション:
echo 'XXAAGGHH (XXXXX) ERRTYTUUUI
AAAAAAAA ( %%))XX) $@@$&%^&&
AADDDDD$ (.SD F@* @) *$%^^&^&&&
AA^@%%^^ ()[))DS((]) RTTYUU' | sed -r 's/^[^(]*\(|\)[^)]*$//g'
XXXXX
%%))XX
.SD F@* @
)[))DS((]
またはファイルの場合:
gawk '{r=gensub(/^[^(]*\((.*)\)[^)]*$/,"\\1","g",$0);print r}' input_file
# OR
awk '{gsub(/^[^(]*\(|\)[^)]*$/,"",$0);print $0}' input_file
# OR
sed -r 's/^[^(]*\(|\)[^)]*$//g' input_file
# all output:
XXXXX
%%))XX
.SD F@* @
)[))DS((]
このように学習しようとするのは非常に悪い考えですが、自分で調べるために正規表現に頭をぶつけることに代わる方法はありません。そうでなければ、実際に学ぶことはできません。私の考えでは、プログラミングでは正規表現よりも価値のある長期学習はありません。
ルールは簡単です。行を終了するすべてのa以外の項目(行を開始してから最初の項目(および無視または削除し、a以外のすべての項目と最後の項目)を追加)を取得し、それを無視または削除します。与えられた答えには、この場合2つのオプションがあることがわかります。行の始まりと終わりを切り取り、目的の結果を取得するか、行の始まりと終わりを無視して目的の結果を得て、結果を印刷します。結果。
パターンがあれば、それを実装するためにどの言語やツールを使用するかはそれほど重要ではありません。