Verwenden von regulären Ausdrücken und Abschnitten, um einen Befehl auszuführen

4448
Ross Rogers

Ähnlich wie bei dieser Frage möchte ich in Linux tcsh eine Protokolldatei abschließen, und wenn ich einen regulären Ausdruck finde, möchte ich einen beliebigen Befehl ausführen. Wie kann ich das machen?

1

4 Antworten auf die Frage

3
wfaulk

Dies scheint für ein kurzes Perl-Skript geeignet zu sein:

#!/usr/bin/perl  while (<>) { last if /regex/; } system("ls"); 

Wenn Sie ein Muster und einen Befehl mit als gekennzeichneten Argumenten angeben möchten, lesen Sie die Dokumentation unter perldoc Getopt::Std.

I really wanted "<> until /regex/;" to work, but I couldn't make it happen. wfaulk vor 15 Jahren 1
perl -Mwarnings -e 'scalar <> until /a/' -- note the warning. ayrnieu vor 15 Jahren 1
2
quack quixote

In der Notiz des Posters führt ein Kommentar in dieser Frage zu einem SO-Posting zum Deaktivieren der automatischen Pufferung bei Verwendung von Pipes . Die Lösung war die Verwendung von Unpuffer (von erwarten ), wie in:

$ unbuffer tail -f foo | find-and-run "findwhat" "runwhat" 

wfaulks Antwort (plus Ayrnieos Bereinigung) liefert uns das Skript find-and-run:

#!/usr/bin/perl # run: find-and-run "regex-to-find" "commandtorun" die "usage: $0 <regex> <exec-this> [exec-this-arg1 ...]\n" unless @ARGV >= 2;  my ($re, @run) = @ARGV;   while (<>) { last if /$re/; } exec { $run[0] } @run; 

Hinweis 1: Bei Debian Lenny müssen Sie das Paket "expect-dev" installieren. unbuffer wird als "expect_unbuffer" installiert.

Anmerkung 2: Dies ist völlig ungetestet und völlig naiv. Verwenden Sie dies aus Sicherheitsgründen nicht. Wenn Sie dies verwenden, möchten Sie Ihren Regex wahrscheinlich in Anführungszeichen setzen, um das Ersetzen / Erweitern der Shell zu vermeiden.

Anmerkung 3: Vielen Dank an ayrnieu für die Fertigstellung und Bereinigung von Skripts.

die "usage: regex exec-this [arg1 ...]\n" unless @ARGV >= 2; my ($re, @run) = @ARGV; ... last if /$re/; ... exec { $run[0] } @run ayrnieu vor 15 Jahren 1
exec / system ist nicht so wichtig, aber $ 1 $ 2 wird definitiv fehlschlagen, und die Verwendung ist einfach eine gute Idee. ayrnieu vor 15 Jahren 0
better: "usage: $0 [ ... ]\n" ayrnieu vor 15 Jahren 1
1
Aleksander Adamowski

In meinem Fall (bei RHEL wollte ich tail -n 0 -f file | grep -m 1 patternsofort beenden, wenn ein Muster in der wachsenden Datei auftritt), konnte die einfache Verwendung des Unbuffer- Dienstprogramms aus dem Expect-Paket das Problem aus irgendeinem Grund nicht lösen.

Aber basierend auf einem Blogbeitrag ( http://www.smop.co.uk/blog/index.php/2006/06/26/tail-f-and-awk/ ) habe ich entdeckt, dass die Weiterleitung von Eingaben vom Endstück gestartet wurde in einer subshell hat der trick:

grep -m 1 pattern <(tail -n 0 -f file) 

Dies war jedoch nicht so einfach. Bei der Arbeit in einer interaktiven Shell blieb derselbe Befehl bei der Remote-Ausführung mit SSH wie üblich stehen:

ssh login@hostname 'grep -m 1 pattern <(tail -n 0 -f file)' 

Ich habe entdeckt, dass man in diesem Fall die Ausgabe des Endes mit Hilfe des Unbuffer- Dienstprogramms von Expect aufheben muss:

ssh login@hostname 'grep -m 1 pattern <(unbuffer -p tail -n 0 -f file)' 

Dies darf nicht auf einer interaktiven Shell verwendet werden - Unbuffer verursacht ein ioctl(raw): I/O error!

Der Ratschlag für Sie lautet daher: Wenn die vorgeschlagenen Lösungen nicht funktionieren, versuchen Sie, tail -fin einer Subshell zu starten, und wenn Sie dies in einem Skript oder in einer nicht interaktiven Shell tun möchten, verwenden Sie unbufferoder unbuffer -pmöglicherweise erforderlich.

Übrigens, in diesem Artikel finden Sie eine ausführliche Erklärung des Ausgabepufferproblems: http://www.pixelbeat.org/programming/stdio_buffering/

0
skarface

Ein anderer Ansatz ist die Verwendung eines Programms wie Swatch . Swatch bietet genau das, worüber Sie sprechen, und ein Dutzend anderer Dinge.