IPアドレスを含む文章があります。例えば、
This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only.
上記の文から、IPアドレスのみを印刷したいと思います。これどうやってするの? sed
でこれを行うことができると聞きました
可能ですが、エレガントではありません。
echo 'This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only.' \
| sed 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/'
[0-9]
は任意の数字に一致し、\{1,3\}
は1〜3回繰り返すことができることを意味します。 \.
はドットに一致します。 IP全体は\(...\)
括弧でキャプチャされ、前後にあるものは.*
、つまり0回以上繰り返されるものと一致します。一致する文字列全体(つまり、行全体)は、最初の一致するグループの内容に置き換えられます。
変数を導入することで読みやすくすることができます:
n='[0-9]\{1,3\}'
... | sed "s/.*\($n\.$n\.$n\.$n\).*/\1/"
IPが見つからない場合、文字列全体を出力します。また、256.512.999.666などの無効なIPもチェックしません。
これはgrep
ソリューションです。
echo "$sentence" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
-o
一致する部分のみを印刷します-E
は拡張正規表現に切り替わります[0-9]
)に1回以上(+
)、次にドット(\.
)、さらに数字に一致します...ここでPerl
を使用した別のソリューション:
echo "$sentence" | Perl -l -ne '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ && print $&'
-l
は行末記号(改行)を指定しました-n
は、echo
で指定された入力をループします(複数行になる場合があります)-e
コードが続きますgrep
ソリューションとほぼ同じです。grep
の次のコマンドを使用します。
grep -Eo '[0-9.]+ ' file
またはさらに良い:
grep -oP '\d+\.\d+\.\d+\.\d+' file
または
grep -Eo "([0-9]{1,3}[\.]){3}[0-9]{1,3}" file
私はgrepを使用します:
echo 'This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only.' | grep -oE '((1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.){3}((1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]))'
これは、他の回答とは異なり、有効なIPアドレスのみを出力します
python 3インタープリターでこれを行います。この111.111.111.111
形式のテキストを取得するだけでなく、有効かどうかもチェックします。
>>> import re
>>> import ipaddress
>>> text = "This sentence contains an ip number 1.2.3.4 and 111.111.111.111 451.976.897.786 port number 50, i want to print the IP address only."
>>> foo = re.findall(r'(?<!\S)(?:\d{1,3}\.){3}\d{1,3}(?!\S)', text)
>>> foo
['1.2.3.4', '111.111.111.111', '451.976.897.786']
>>> for i in foo:
... try:
... ipaddress.ip_address(i)
... except:
... pass
...
IPv4Address('1.2.3.4')
IPv4Address('111.111.111.111')
python 3インタープリターを取得するには、ターミナルでpython3
コマンドを入力します。
Chorobaの答えの拡張:
新しい行を印刷せず、IPのみを印刷する場合:
$ echo -e 'This sentence contains an ip number 1.2.3.4 and port number 50, \ni want to print the IP address only.\n One more IP is 1.24.53.3.' \
| sed -n 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/1p'
出力:
1.2.3.4
1.24.53.3
説明:
-n flag is for quiet / silent.
p print the replaced text
RegExpと組み合わせたAWKは、行の一部の処理に非常に適しています。
ワンライナーベローズの基本的な考え方は、ラインをforループし、最大4回繰り返される4つの数字とドットの存在を確認することです。同時に、ポート番号について2〜4回繰り返される数字を確認できます。
awk '{for(i=1;i<=NF;i++) { if ($i~/[[:digit:]\.]{4}/) printf $i; if ( $i~/[[:digit:]]{2,4}/) printf ":"$i }}'
サンプル実行
$ echo "This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only." | awk '{for(i=1;i<=NF;i++) { if ($i~/[[:digit:]\.]{4}/) printf $i; if ( $i~/[[:digit:]]{2,4}/) printf ":"$i }}'
1.2.3.4:50,
あなたの文章には50が含まれており、分離せずに一緒に印刷されますが、gsub(/[[:punct:]]/,"")
は必要に応じて削除できます。