私はbashスクリプトを書き込もうとしています。これは次のことを行います。
例えば:
first_file.txt:
111111
1111
11
1
second_file.txt:
122221
2222
22
2
パターン:
2222
出力:
122221
111111
1111
11
1
2222
111111
1111
11
1
22
2
BASHでこの機能を実現するには何を使用すればよいですか?
コードを書きましたが、正しく機能しません(なぜですか?):
#!/bin/bash
first_filename="$1"
second_filename="$2"
pattern="$3"
while read -r line
do
if [[ $line=˜$pattern ]]; then
while read -r line2
do
echo $line2
done < $second_filename
fi
echo $line
done < $first_filename
=~
演算子の前後にスペースが必要です。比較:
[[ foo=~bar ]]
[[ foo =~ bar ]]
これは、最初の式が基本的に「この文字列は空ですか?」と評価されるためです。
また、OPコードは チルダではなく 小さなチルダ を使用します。
それでも、内側のループを簡単に取り除くことができます。 while read -r line2
ビット全体をcat -- "$second_filename"
に置き換えるだけです。
最後のecho $line
が正しいのは、ファイルが改行文字で終わっていない場合のみです(* nixツールの標準)。代わりに、while read -r line || [[ $line ~= '' ]]
を使用する必要があります。これは、最後に改行がある場合とない場合で機能します。
また、 se MoreQuotes™ 。
sed
はループなしでそれを行うことができます。そのr
コマンドを使用します。
sed -e '/pattern/rFILE1' FILE2
テストセッション:
$ cd -- "$(mktemp -d)"
$ printf '%s\n' 'nuts' 'bolts' > first_file.txt
$ printf '%s\n' 'foo' 'bar' 'baz' > second_file.txt
$ sed -e '/bar/r./first_file.txt' second_file.txt
foo
bar
nuts
bolts
baz
awkの使用も同様に機能します。
###マーカー###行の前に挿入するには:
// for each <line> of second_file.txt :
// if <line> matches regexp ###marker###, outputs first_file.txt.
// **without any condition :** print <line>
awk '/###marker###/ { system ( "cat first_file.txt" ) } \
{ print; } \' second_file.txt
###マーカー###行の後に挿入するには:
// for each <line> of second_file.txt :
// **without any condition :** print <line>
// if <line> matches regexp ###marker###, outputs first_file.txt.
awk '{ print; } \
/###marker###/ { system ( "cat first_file.txt" ) } \' second_file.txt
### marker ###行を置き換えるには:
// for each <line> of second_file.txt :
// if <line> matches regexp ###marker###, outputs first_file.txt.
// **else**, print <line>
awk '/###marker###/ { system ( "cat first_file.txt" ) } \
!/###marker###/ { print; }' second_file.txt
インプレース置換を行う場合は、一時ファイルを使用して、awkがファイル全体を読み取る前にパイプが開始されないようにします。追加 :
> second_file.txt.new
mv second_file.txt{.new,}
// (like "mv second_file.txt.new second_file.txt", but shorter to type !)
行の内側を置き換えたい場合(パターンだけを置き換え、行の残りを維持する)、同様の解決策がsedで達成できるはずです。 awkの代わりに。
私はこのようにsedを使用し、それは魅力として機能しました
sed -i -e '/ pattern/r filetoinsert' filetobeinserted
指定されたパターンの行の後に「filetoinsert」を「filetobeinserted」に挿入します。
一意のパターンを選択するように注意してください。重複するパターンでどのように機能するかはわかりません。最初のパターンだけで機能すると思います。
これは機能するはずです:
Perl -lne 'BEGIN{open(A,"first_file.txt");@f=<A>;}print;if(/2222/){print @f}' second_file.txt
テスト済み:
> cat temp
111111
1111
11
1
> cat temp2
122221
2222
22
2
> Perl -lne 'BEGIN{open(A,"temp");@f=<A>;}print;if(/2222/){print @f}' temp2
122221
111111
1111
11
1
2222
111111
1111
11
1
22
2
>