ソースファイルには以下が含まれます。
# launch our autostart apps (if we are on the correct tty and not in X)
if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then
bash "/opt/retropie/configs/all/autostart.sh"
fi
検索文字列は次のとおりです。
if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then
bash "/opt/retropie/configs/all/autostart.sh"
rebootWithoutWiimotes=0 /home/pi/attachwii.sh
この行の前に追加して、次のように見せたいと思います。
# launch our autostart apps (if we are on the correct tty and not in X)
rebootWithoutWiimotes=0 /home/pi/attachwii.sh
if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then
bash "/opt/retropie/configs/all/autostart.sh"
fi
私はさまざまなsed
コマンドを試してみました。sudo sed -i '\% bash "/opt/retropie/configs/all/autostart.sh"%i rebootWithoutWiimotes=0 /home/pi/attachwii.sh' 10-retropie.sh
これにより、誤ったファイルが生成されます。
# launch our autostart apps (if we are on the correct tty and not in X)
if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then
rebootWithoutWiimotes=0 /home/pi/attachwii.sh
bash "/opt/retropie/configs/all/autostart.sh"
fi
私が試した場合:
sudo sed -i '\% if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then bash "/opt/retropie/configs/all/autostart.sh"%i rebootWithoutWiimotes=0 /home/pi/attachwii.sh%' 10-retropie.sh
元のファイルから何の変更も得られませんでした。次のようにしても機能しません。
sudo sed -i '\% if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then%i rebootWithoutWiimotes=0 /home/pi/attachwii.sh' 10-retropie.sh
数日間、さまざまなバリエーションをテストし、正規sed
表現について多くを学びましたが、この部分は理解できません。
sed
ファイルの正確な部分があることを確認するために、これらの2行を検索してから、これら2つの検索行の前に追加したい行を追加するにはどうすればよいですか?
ベストアンサー1
これはsedで実行するPITAですが、sed
Perlではかなり簡単です(sedで可能であると100%確信していません...おそらくそうです。しかし、sedを使って試してみる必要はないと確信しています。これを行います)。
#!/usr/bin/perl
use strict;
my $found = undef;
my $insert = "rebootWithoutWiimotes=0 /home/pi/attachwii.sh";
my @lines = (<>); # slurp entire file in @lines array
# iterate over @lines, looking for our two consecutive lines
foreach my $i (0 .. $#lines) {
# abort if we've already inserted the line
exit 1 if $lines[$i] =~ m:\Q$insert\E:;
if ( $lines[$i ] =~ m:if.*tty.*/dev/tty1.*DISPLAY.*USER.*pi:
&& $lines[$i+1] =~ m:bash "/opt/retropie/configs/all/autostart.sh":
) {
$found = $i;
last;
};
};
# if we found them, insert our new line immediately before them.
if (defined($found)) {
splice @lines, $found, 0, "$insert\n";
print @lines;
} else { exit 1 };
\Q
正規表現マッチングに使用する場合、Perl に\E
正規表現メタ文字をエスケープして$insert
文字列リテラルとして処理するように指示します。
たとえば、別の名前で保存してinsert-attach.pl
実行可能にし、chmod +x insert-attach.pl
次のように実行します。
$ ./insert-attach.pl 10-retropie.sh
# launch our autostart apps (if we are on the correct tty and not in X)
rebootWithoutWiimotes=0 /home/pi/attachwii.sh
if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then
bash "/opt/retropie/configs/all/autostart.sh"
fi
いいですね。これにより、変更されたファイルは標準出力に印刷されますが、ファイルを置き換えようとします。したがって、次のように実行します。
$ ./insert-attach.pl 10-retropie.sh > 10-retropie.sh.new \
&& mv -fv 10-retropie.sh.new 10-retropie.sh
renamed '10-retropie.sh.new' -> '10-retropie.sh'
$ cat 10-retropie.sh
# launch our autostart apps (if we are on the correct tty and not in X)
rebootWithoutWiimotes=0 /home/pi/attachwii.sh
if [ "`tty`" = "/dev/tty1" ] && [ -z "$DISPLAY" ] && [ "$USER" = "pi" ]; then
bash "/opt/retropie/configs/all/autostart.sh"
fi
元のファイルのみが置き換えられます。もし修正が成功しました。
Perlでこれを行うには他の方法があります(そのうちのいくつかは、入力ファイルがギガバイトのテキストのように大きい場合に適しています)。ただし、これはPerlを使用して実行できる方法の良いチュートリアルの例です。
ただし、必要に応じて複数の行を挿入できます。この関数の最後のパラメータsplice
はリストです。
たとえば、これは改行文字、行、およびrebootWithout...
他の2つの改行文字を挿入します。
splice @lines, $found, 0, "\n", $insert, "\n\n";
@insert
スカラー変数の代わりに配列を使用することもできます。ただし、1つだけを選択するのではなく、一意の要素の1つを確認するには$insert
テストを変更する必要があります。exit 1 if $lines[$i] =~ ....
@insert
$insert
いいえ元のファイルにあります。)例えば:
#!/usr/bin/perl
use strict;
my $found = undef;
my @insert = (
"\n",
"# run the attachwii.sh script",
"rebootWithoutWiimotes=0 /home/pi/attachwii.sh",
"\n",
"\n",
);
my @lines = (<>); # slurp entire file in @lines array
# iterate over @lines, looking for our two consecutive lines
foreach my $i (0 .. $#lines) {
# abort if we've already inserted the line
# (note: perl arrays start from 0, not 1, so $insert[2] is the third element)
exit 1 if $lines[$i] =~ m:\Q$insert[2]\E:;
if ( $lines[$i ] =~ m:tty.*/dev/tty1.*DISPLAY.*USER.*pi:
&& $lines[$i+1] =~ m:bash "/opt/retropie/configs/all/autostart.sh":
) {
$found = $i;
last;
};
};
# if we found them, insert our new lines immediately before them.
if (defined($found)) {
splice @lines, $found, 0, @insert;
print @lines;
} else { exit 1 };