4

このhtmlコードでは:

<div id="ajaxWarningRegion" class="infoFont"></div>
  <span id="ajaxStatusRegion"></span>
  <form enctype="multipart/form-data" method="post" name="confIPBackupForm" action="/cgi-bin/utilserv/confIPBackup/w_confIPBackup" id="confIPBackupForm" >
    <pre>
      Creating a new ZIP of IP Phone files from HTTP/PhoneBackup 
      and HTTPS/PhoneBackup
    </pre>
    <pre> /tmp/IP_PHONE_BACKUP-2012-Jul-25_15:47:47.zip</pre>
    <pre>Reports Success</pre>
    <pre></pre>
    <a href =  /tmp/IP_PHONE_BACKUP-2012-Jul-25_15:47:47.zip>
      Download the new ZIP of IP Phone files
    </a>
  </div>

テキストまたはとIP_PHONE_BACKUP-2012-Jul-25_15:47:47.zipの間の日付と時刻だけを取得したいIP_PHONE_BACKUP-.zip

どうやってやるの ?

4

4 に答える 4

10

この質問を興味深いものにしているのは、HTML が XML と同じように見えて匂いがすることです。理想的な世界では HTML は XML のサブセットですが、実際の HTML は明らかにXML ではありません。質問の例を任意の XML パーサーに入力すると、さまざまな違反が発生します。そうは言っても、1 行の PowerShell で目的の結果を得ることができます。これは、href のテキスト全体を返します。

Select-NodeContent $doc.DocumentNode "//a/@href"

そして、これは目的の部分文字列を抽出します:

Select-NodeContent $doc.DocumentNode "//a/@href" "IP_PHONE_BACKUP-(.*)\.zip"

ただし、問題は、その 1 行のコードを実行できるようにするためのオーバーヘッド/セットアップにあります。必要がある:

  • HtmlAgilityPackをインストールして、HTML 解析を XML 解析のように見せます。
  • ライブ Web ページを解析する場合は、PowerShell Community Extensionsをインストールします。
  • XPathを理解して、ターゲット ノードへのナビゲート可能なパスを構築できるようにします。
  • 正規表現を理解して、ターゲット ノードから部分文字列を抽出できるようにします。

これらの要件が満たされると、HTMLAgilityPath型を環境に追加し、Select-NodeContent関数を定義できます。両方を以下に示します。$docコードの最後は、上記のワンライナーで使用される変数に値を割り当てる方法を示しています。必要に応じて、ファイルまたは Web から HTML をロードする方法を示します。

Set-StrictMode -Version Latest
$HtmlAgilityPackPath = [System.IO.Path]::Combine((Get-Item $PROFILE).DirectoryName, "bin\HtmlAgilityPack.dll")
Add-Type -Path $HtmlAgilityPackPath

function Select-NodeContent(
    [HtmlAgilityPack.HtmlNode]$node,
    [string] $xpath,
    [string] $regex,
    [Object] $default = "")
{
    if ($xpath -match "(.*)/@(\w+)$") {
        # If standard XPath to retrieve an attribute is given,
        # map to supported operations to retrieve the attribute's text.
        ($xpath, $attribute) = $matches[1], $matches[2]
        $resultNode = $node.SelectSingleNode($xpath)
        $text = ?: { $resultNode } { $resultNode.Attributes[$attribute].Value } { $default }
    }
    else { # retrieve an element's text
        $resultNode = $node.SelectSingleNode($xpath)
        $text = ?: { $resultNode } { $resultNode.InnerText } { $default }
    }
    # If a regex is given, use it to extract a substring from the text
    if ($regex) {
        if ($text -match $regex) { $text = $matches[1] }
        else { $text = $default }
    }
    return $text
}

$doc = New-Object HtmlAgilityPack.HtmlDocument
$result = $doc.Load("tmp\temp.html") # Use this to load a file
#$result = $doc.LoadHtml((Get-HttpResource $url)) # Use this  PSCX cmdlet to load a live web page
于 2012-07-25T18:40:43.313 に答える
1

実際、ファイル名を囲む HTML はここでは関係ありません。次の正規表現を使用すると、日付をうまく抽出できます (電子メール、HTML ページ、または CSV ファイルから抽出するかどうかは気にしません)。

(?<=/tmp/IP_PHONE_BACKUP-)[^.]+(?=\.zip)

クイックテスト:

PS> [regex]::Match($html, '(?<=/tmp/IP_PHONE_BACKUP-)[^.]+(?=\.zip)')

Groups   : {2012-Jul-25_15:47:47}
Success  : True
Captures : {2012-Jul-25_15:47:47}
Index    : 391
Length   : 20
Value    : 2012-Jul-25_15:47:47
于 2012-07-26T05:12:55.687 に答える
0

次の正規表現の group(2) と group(3) には、日付と時刻が含まれています。

/IP_PHONE_BACKUP-((.*)_(.*)).zip/

これは、powershell で正規表現から値を抽出するためのリンクです。

Powershell 正規表現からグループを引き出すより短い方法はありますか?

ハイ

于 2012-07-25T14:08:33.657 に答える
0

正規表現なし:

$a = '<div id="ajaxWarningRegion" class="infoFont"></div><span id="ajaxStatusRegion"></span><form enctype="multipart/form-data" method="post" name="confIPBackupForm" action="/cgi-bin/utilserv/confIPBackup/w_confIPBackup" id="confIPBackupForm" ><pre>Creating a new ZIP of IP Phone files from HTTP/PhoneBackup and HTTPS/PhoneBackup</pre><pre> /tmp/IP_PHONE_BACKUP-2012-Jul-25_15:47:47.zip</pre><pre>Reports Success</pre><pre></pre><a href =  /tmp/IP_PHONE_BACKUP-2012-Jul-25_15:47:47.zip>Download the new ZIP of IP Phone files</a></div>'
$a.Substring($a.IndexOf("IP_PHONE_BACKUP")+"IP_PHONE_BACKUP".length+1, $a.IndexOf(".zip")-$a.IndexOf("IP_PHONE_BACKUP")-"IP_PHONE_BACKUP".length-1)

Substring元の文字列の一部を取得します。最初のパラメータは部分文字列の開始位置で、2 番目の部分は目的の部分文字列の長さです。だから今あなたがしなければならないのは、ちょっとした魔法を使って開始点と長さを計算することだけIndexOfですLength

于 2012-07-25T14:12:56.270 に答える