Perl 正则表达式匹配 `w -hs` 命令的输出

发布于 2024-09-04 06:21:51 字数 1785 浏览 7 评论 0原文

我正在尝试编写一个 Perl 脚本,它可以更好地与 KDE 的 kwrited 配合使用,据我所知,它连接到 pts 并将通过 KDE 系统托盘通知收到的每一行标题为“KDE write daemon”。

不幸的是,它为每一行发出单独的通知,因此它会在常规旧 write,并且由于某种原因,在使用 。一行消息也已不复存在。

我还希望使它能够通过具有胖客户端的 LAN 进行广播。在开始之前(当然,这需要 SSH),我尝试制作一个无 SSH 的版本以确保它可以工作。不幸的是,它没有:

perl ./write.pl "Testing 1 2 3"

其中以下是 ./write.pl 的内容:

#!/usr/bin/perl

use strict;
use warnings;

my $message = "";
my $device = "";
my $possibledevice = '`w -hs | grep "/usr/bin/kwrited"`'; #Where is kwrited?
$possibledevice =~ s/^[^\t][\t]//;
$possibledevice =~ s/[\t][^\t][\t ]\/usr\/bin\/kwrited$//;
$possibledevice = '/dev/'.$possibledevice;
unless ($possibledevice eq "") {
    $device = $possibledevice;
}

if ($ARGV[0] ne "") {
    $message = $ARGV[0];
    $device = $ARGV[1];
}
else {
    $device = $ARGV[0] unless $ARGV[0] eq "";
    while (<STDIN>) {
        chomp;
        $message .= <STDIN>;
    }
}

if ($message ne "") {
    system "echo \'$message\' > $device";
}
else {
    print "Error: empty message"
}

产生以下错误:

$ perl write.pl "Testing 1 2 3"
Use of uninitialized value $device in concatenation (.) or string at write.pl line 29.
sh: -c: line 0: syntax error near unexpected token `newline'
sh: -c: line 0: `echo 'foo' > '

不知何故,正则表达式和/或反引号在处理 $possibledevice 时转义 无法正常工作,因为在 kwrited 连接到 /dev/pts/0 的情况下,以下工作完美:

$ perl write.pl "Testing 1 2 3" /dev/pts/0

I'm trying to write a Perl script that will work better with KDE's kwrited, which, as far as I can tell, is connected to a pts and puts every line it receives through the KDE system tray notifications with the title "KDE write daemon".

Unfortunately, it makes a separate notification for each and every line, so it spams up the system tray with multiline messages on regular old write, and for some reason it cuts off the entire last line of the message when using wall. One-line messages are also goners.

I was also hoping to make it so that it could broadcast across a LAN with thick clients. Before starting on that (which would require SSH, of course), I tried to make an SSH-less version to make sure it works. Unfortunately, it doesn't:

perl ./write.pl "Testing 1 2 3"

where the following is the contents of ./write.pl:

#!/usr/bin/perl

use strict;
use warnings;

my $message = "";
my $device = "";
my $possibledevice = '`w -hs | grep "/usr/bin/kwrited"`'; #Where is kwrited?
$possibledevice =~ s/^[^\t][\t]//;
$possibledevice =~ s/[\t][^\t][\t ]\/usr\/bin\/kwrited$//;
$possibledevice = '/dev/'.$possibledevice;
unless ($possibledevice eq "") {
    $device = $possibledevice;
}

if ($ARGV[0] ne "") {
    $message = $ARGV[0];
    $device = $ARGV[1];
}
else {
    $device = $ARGV[0] unless $ARGV[0] eq "";
    while (<STDIN>) {
        chomp;
        $message .= <STDIN>;
    }
}

if ($message ne "") {
    system "echo \'$message\' > $device";
}
else {
    print "Error: empty message"
}

produces the following error:

$ perl write.pl "Testing 1 2 3"
Use of uninitialized value $device in concatenation (.) or string at write.pl line 29.
sh: -c: line 0: syntax error near unexpected token `newline'
sh: -c: line 0: `echo 'foo' > '

Somehow, the regular expressions and/or the backtick escape in processing $possibledevice are not working properly, because where kwrited is connected to /dev/pts/0, the following works perfectly:

$ perl write.pl "Testing 1 2 3" /dev/pts/0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瞄了个咪的 2024-09-11 06:21:51

您仅提供一个命令行参数(字符串“Testing 1 2 3”)。

所以 $ARGV[1] 是 undef 的。

因此,由于 if ($ARGV[0] ne "") 内部的逻辑, $device 是 undef 。

因此,你的 shell 的 echo 命令重定向到任何内容(“echo Something >”),因此 shell 会发出抱怨(这也是“undefined $device”Perl 警告的来源) 。

如果您的意思是设备为“1”,则在命令行上取消引用您的参数字符串 (perl write.pl Testing 1 2 3)。

另外,请考虑将 $device 作为文件打开,以便将“$message”写入并打印到文件句柄。它是更惯用的 Perl,并且不太容易出现因 Perl 到 shell 转换/引用/等引起的问题...

You supply only ONE command line argument (string "Testing 1 2 3").

So $ARGV[1] is undef.

So $device is undef because of the logic inside if ($ARGV[0] ne "") .

So your shell's echo command redirects to nothing ("echo something >") and thus shell complains (and that's where "undefined $device" Perl warning is from as well).

If you meant the device to be "1", then un-quote your argument string (perl write.pl Testing 1 2 3) on command line.

Also, please consider opening $device as a file for writing and printing "$message" to the file handle. It's a bit more idiomatic Perl and less prone to problems stemming from perl-to-shell transitions/quoting/etc...

燕归巢 2024-09-11 06:21:51

一个问题是您尝试的系统调用周围的 ' 。 Perl 中的单引号内不会发生插值。

如果您看一个简单的情况:

#!/usr/bin/perl

use strict;
use warnings;


my $possibledevice = '`w -hs | grep "/usr/bin/kwrited"`'; #Where is kwrited?
print $possibledevice;

输出为:

`w -hs | grep "/usr/bin/kwrited"`

因此您的 shell 调用永远不会发生。解决方法是将 shell 调用更改为更像这样的内容:

my $possibledevice = `w -hs | grep \"/usr/bin/kwrited\"`; #shud b there...
#or
my $possibledevice = qx$w -hs | grep \"/usr/bin/kwrited\"$; #alternate form

您可以在 perlop 或 perldoc 这里

有一个反引号、系统和 shell 教程 此处

One problem is your ' around the attempted system call. No interpolation takes place inside single quotes in Perl.

If you look at a simple case:

#!/usr/bin/perl

use strict;
use warnings;


my $possibledevice = '`w -hs | grep "/usr/bin/kwrited"`'; #Where is kwrited?
print $possibledevice;

The output is:

`w -hs | grep "/usr/bin/kwrited"`

So your shell call never takes place. The fix is to change the shell call to something more like this:

my $possibledevice = `w -hs | grep \"/usr/bin/kwrited\"`; #shud b there...
#or
my $possibledevice = qx$w -hs | grep \"/usr/bin/kwrited\"$; #alternate form

You can read about the different quote like operators in perlop or at perldoc HERE

There is a backtick, system and shell tutorial HERE

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文