![](/img/trans.png)
[英]basic perl: regex statement not working in perl 5.10.1 machine but works in 5.18?
[英]Perl regex to extract machine name from hostname
我在CentOS 6.8上使用Perl v5.10
我的程序將主機名列表讀入Perl數組@aVmList
。 我試圖從它們中僅提取機器名稱。
有些主機名是完全限定的,有些則不是。 有些包含破折號或下划線。
我無法控制數組的內容。
這是我正在使用的數據的示例。
my @aVmList = qw(
vmserver1.domain.com
vmserver2
vm-server-three.otherdomain.com
server_four.domain.com
server5
server6
some-silly-vm-name
another_server.maybewithadomain.com
);
我只想從每個元素中提取機器名稱,最后得到以下內容。
vmserver1
vmserver2
vm-server-three
server_four
server5
server6
some-silly-vm-name
another_server
我發現正則表達式/(.*?)\\./
幾乎可以使用,但是僅當所有名稱都完全限定時才可以。
foreach ( @aVmList ) {
$_ =~ /(.*?)\./;
my $sVmName = $1;
print $sVmName;
}
我以為我需要對這些點進行回顧。 我想出了以下幾點
$_ =~ /([A-Za-z0-9-_]+)(?!=\.)/;
似乎可以在regex測試器中使用,但是當我運行Perl腳本時,它仍然與整個字符串匹配。
我不喜歡上面的正則表達式模式所使用的路徑,因為現在我假設主機名將僅包含“單詞”字符或連字符。
我知道我不必在主機名中考慮特殊字符,但是我正在嘗試將正則表達式模式基於匹配域名suffix.something.com
第一個點之前的任何內容。
我還發現了正則表達式從完全合格的域名中提取主機名 ,這聽起來像我想要的,但是那里的任何建議似乎都沒有用。
我試過了:
$_ =~ (.+?)(?=\.)
和
$_ =~ ^([^.]+)\..*$
在否定字符類 [^...]
匹配除了列出的任何字符。 然后
my ($name) = $_ =~ /([^.]+)/;
匹配所有字符,直到第一個.
並停在該位置,因此沒有理由明確匹配該點(也不匹配該行的其余部分)。 匹配被捕獲並分配給$name
。
在列表上下文中使用match運算符時,它將返回所有匹配項的列表
my @matches = $var =~ m/$pattern/g;
即使只有一個匹配項,我們也需要列表上下文以便返回匹配項 ,因此my ($name) = ...
的括號將列表上下文強加到match運算符上。 在上面的示例中,這是通過分配給數組來完成的。 否則,我們將擁有標量上下文 ,在這種情況下,匹配運算符的行為會有所不同。 看到這個在perlop得到和看到perlretut 。
上面的m
可以省略,最常見的是。 但是請注意,並非總是如此,例如,使用不同的距離時。 我建議通讀perlretut
。
循環中的默認輸入和模式搜索空間 ( $_
)保存當前處理的元素。 默認情況下,正則表達式可與$_
因此無需指定$_
。 請參閱perlvar中的常規變量 ,並在perlop
鏈接中查看與正則表達式相關的注釋。 所以你可以做
foreach (@vm_list) {
/([^.]+)/; # OK but better assign directly from the match
my $host_name = $1;
}
但是,從答案中直接分配更清晰。
我認為您正在使此過程變得比所需的復雜。 分割時間段並使用第一部分:
use strict;
use warnings;
use 5.012;
while (<DATA>) {
chomp;
say ((split(/\./))[0]);
}
__DATA__
vmserver1.domain.com
vmserver2
vm-server-three.otherdomain.com
server_four.domain.com
server5
server6
some-silly-vm-name
another_server.maybewithadomain.com
輸出:
vmserver1
vmserver2
vm-server-three
server_four
server5
server6
some-silly-vm-name
another_server
沒有“完全限定”或“部分限定”主機名之類的東西。 主機名是URL協議名稱之后的第一部分,其內容與協議有關且與主機有關。 在編寫正則表達式模式之前,必須定義您的意思
分隔字符串中用點分隔的部分很容易,但是您尚未指定所需的部分。 感覺就像您在撒謊,編寫各種隨機代碼,希望其中之一能起作用
這並不是真正的答案,在您完全確定需要的內容之前,您永遠不會獲得正確的解決方案。 在獲得正確的樣本輸入之前,一直嘗試嘗試是非常錯誤的。 如果這樣發布,您的軟件就會拋棄您公司的業務。 您的代碼必須對可能的所有輸入都起作用。 這就是為什么您必須理解需求的含義 ,而不僅僅是單詞和少量數據的原因
您是否被迫使用@aVmList
這樣的匈牙利符號? 它不再很流行,在Perl中也沒有位置,在開頭的@
表示該項目是一個數組,因此a
是多余的,使程序的可讀性降低。 這是Perl的方法,可以避免在詞法變量的標識符中使用大寫字母,因此您的數組會比@vm_list
更好
您的第一次嘗試
$_ =~ /(.*?)\./;
與...相同
/(.*?)\./;
這除了在模式匹配時可能設置$1
之外什么都不做。 您似乎尚未掌握$_
的用途,並且不是在此處進行詳細說明的地方
忘了環顧四周的構造。 您需要做的第一件事是定義一個規則 ,以提取主機名的必需部分。 查看主機名時如何做
abcdco.jp
會abcdco.jp
?
abcvm-server-three.otherdomain.com.server_four.domain.com.co.uk
會abcvm-server-three.otherdomain.com.server_four.domain.com.co.uk
?
您不能以您的代碼永遠不會看到這樣的字符串為基礎來注銷它們。 如果不能確定調用代碼已經對它們進行了驗證,那么在嘗試提取適當的部分之前,必須自己檢查它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.