소스 파일에는 다음이 포함됩니다.
# 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
파일의 정확한 부분이 있는지 확인하기 위해 이 두 줄을 검색한 다음 이 두 검색 줄 앞에 추가하려는 줄을 추가하려면 어떻게 해야 합니까 ?
답변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...
및 다른 두 개의 개행 문자를 삽입합니다.
splice @lines, $found, 0, "\n", $insert, "\n\n";
@insert
스칼라 변수 대신 배열을 사용할 수도 있습니다 . 하지만 단지 하나를 선택하는 대신 더 고유한 요소 중 하나를 확인하려면 $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 };