簡體   English   中英

Perl正則表達式從主機名中提取計算機名

[英]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.jpabcdco.jp

abcvm-server-three.otherdomain.com.server_four.domain.com.co.ukabcvm-server-three.otherdomain.com.server_four.domain.com.co.uk

您不能以您的代碼永遠不會看到這樣的字符串為基礎來注銷它們。 如果不能確定調用代碼已經對它們進行了驗證,那么在嘗試提取適當的部分之前,必須自己檢查它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM