В дополнение к полезному ответу @ Avinash Raj с более общим решением, совместимым с POSIX.
Обратите внимание, что решение равно awk
], потому что надежное портативное решение с sed
практически невозможно из-за ограничений правильных выражений POSIX ' basic .
awk -v commentId='#' -v word='2001' '
$0 ~ "(^|[[:punct:][:space:]])" word "($|[[:punct:][:space:]])" {
if (match($0, "^[[:space:]]*" commentId))
$0 = substr($0, RSTART + RLENGTH)
else
$0 = commentId $0
}
{ print }
' file > tmpfile.$$ && mv tmpfile.$$ file
(^|[[:punct:][:space:]])
и ($|[[:punct:][:space:]])
являются расширенными эквивалентами регулярных выражений POSIX в словарных границах \<
и \>
, известных из других диалектов regex. awk
не предлагает на месте (также не относится к POSIX sed
), поэтому вывод сначала фиксируется во временном файле, и этот файл затем заменяет оригинал на успех. Сохранение IPv4-адреса в виде двоичного файла
(4) наиболее точно соответствует тому, что он представляет, и позволяет легко Запросы в стиле маски подсети. Однако он требует преобразования внутрь и обратно, если вы действительно хотите текстовое представление. В этом случае вы можете предпочесть строковый формат.
Между прочим, мало используемая функция SQL Server, которая может помочь, если вы сохраняете как строку, - это PARSENAME
. Не предназначен для IP-адресов, но идеально для них подходит. Приведенный ниже вызов вернет «14»:
SELECT PARSENAME('123.234.23.14', 1)
(нумерация справа налево).
он требует преобразования внутрь и обратно, если вы действительно хотите текстовое представление. В этом случае вы можете предпочесть строковый формат. Между прочим, мало используемая функция SQL Server, которая может помочь, если вы сохраняете как строку, - это PARSENAME
. Не предназначен для IP-адресов, но идеально для них подходит. Приведенный ниже вызов вернет «14»:
SELECT PARSENAME('123.234.23.14', 1)
(нумерация справа налево).
он требует преобразования внутрь и обратно, если вы действительно хотите текстовое представление. В этом случае вы можете предпочесть строковый формат. Между прочим, мало используемая функция SQL Server, которая может помочь, если вы сохраняете как строку, - это PARSENAME
. Не предназначен для IP-адресов, но идеально для них подходит. Приведенный ниже вызов вернет «14»:
SELECT PARSENAME('123.234.23.14', 1)
(нумерация справа налево).
Цитирование это :
Сохранение IP-адресов в столбце CHAR (15). В зависимости от того, сколько данных вы храните, это может быть довольно расточительным (зачем нам хранить точки?). I
Мне удалось создать четыре столбца smallint (или любого другого типа небольших целочисленных данных, который вы предпочитаете) - по одному для каждого октета. Затем вы можете создать представление, которое объединяет их в виде строки символов (для отображения), или затем вы можете написать простые операторы, чтобы определить, кто все в какой подсети и т. Д.
Это довольно быстро (при условии правильной индексации) а также позволяет очень легко выполнять запросы (без манипуляций со строками!).
Не забывайте про IPv6 - вам понадобится гораздо больше места, если вам нужно их хранить - 128 бит по сравнению с 32 в IPv4.
Я бы выбрал bigint, хотя вам понадобится некоторый вспомогательный код для перевода в удобные для человека версии.
Я бы, вероятно, выбрал varchar
или char
.
И установил размер 15.
IPV4? int? или tinyint x 4?
Это действительно зависит от того, будет ли это просто хранение и извлечение или это будет критерий ранжированного поиска.
Поскольку в IP-адресе 32 бита, можете ли вы просто использовать LONG для хранения числового значения?
Это не будет так расточительно, как использование VARCHAR, но тогда вам придется каждый раз декодировать его обратно в IP, прежде чем использовать его, а задержка и накладные расходы могут не окупиться.
В одной из моих любимых статей рассказывается о том, почему не следует использовать регулярные выражения для анализа IP-адресов. Большая часть того, о чем они говорят, действительно объясняет, почему вы должны быть очень осторожны с текстовым представлением IP-адресов. Я предлагаю вам прочитать его, прежде чем решать, какой тип данных использовать в вашей базе данных, и, вероятно, также для любой обработки вашего приложения (хотя статья написана о Perl, она полезна для любого языка).
Я думаю, что в конец 32-битный тип данных (или четыре 8-битных типа данных) будет лучшим выбором.
Для эффективного хранения данных и когда значения должны быть обработаны (сопоставлены или сравниваются с диапазоном), я использую int
. IP-адрес на самом деле представляет собой 32-битное значение.
Для простого решения, когда вы просто хотите сохранить значение для его просмотра, я использую varchar (15)
для хранения строкового представления IP-адрес.
Обычно я просто использую varchar (15) для адресов IPv4, но сортировка их - это боль, если вы не добавляете нули.
Я также хранил их как INT в прошлом. System.Net.IPAddress
имеет метод GetAddressBytes
, который возвращает IP-адрес в виде массива из 4 байтов, представляющих IP-адрес. Вы можете использовать следующий код C # для преобразования IPAddress
в int
...
var ipAsInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
Я использовал это, потому что мне пришлось много искать дублированные адреса, и хотел, чтобы индексы были как можно меньше и быстрее. Затем, чтобы вытащить адрес обратно из int в объект IPAddress
в .net, используйте метод GetBytes
на BitConverter
, чтобы получить int в виде байта. массив. Передайте этот массив байтов конструктору для IPAddress
, который принимает массив байтов, и вы получите резервную копию с IPAddress
, с которого начали.
var myIp = new IPAddress(BitConverter.GetBytes(ipAsInt));
Относительно этого комментария в принятом ответе
их сортировка затруднительна, если вы не наберете нули.
Вот трюк для SQL Server 2008 (от Ицика Бен-Гана в этой книге )
with ip_addresses as
(
SELECT '131.33.2.201' AS ip_address UNION ALL
SELECT '2.12.4.4' AS ip_address UNION ALL
SELECT '131.33.2.202' AS ip_address UNION ALL
SELECT '2.12.4.169' AS ip_address UNION ALL
SELECT '131.107.2.201' AS ip_address
)
select ip_address
from ip_addresses
ORDER BY CAST('/' + ip_address + '/' AS hierarchyid)
Возвращает
ip_address
-------------
2.12.4.4
2.12.4.169
131.33.2.201
131.33.2.202
131.107.2.201
Лучший способ (когда нет необходимости в сортировке и другом контроле IP-адресов) - сохранить его как int , сохранение его как varchar и т. Д. Будет стоить намного больше производительности, чем просто простое невинное int.
Есть свойство IPAddress.Address
, но оно устарело, я не знаю почему, поскольку, если вам не нужна сортировка или контроль над классами IP, лучше всего сохранить его как целое число без знака (которое имеет максимальное значение 0xffffffff
, что равно 255.255.255.255
в десятичном представлении.
Также класс IPAddress имеет конструктор, который принимает длинный аргумент.
] И, согласно визуализатору отладчика VS, этот класс IPAddress сам хранит свою внутреннюю переменную как одно число (а не массив байтов).
Подробнее об обходных путях сохранения единицы в MS SQL Server:
Я читаю здесь много похожих вопросов, и ни один из ответов в этом не упоминает ответ номер один в других: "Для IPv4-адресов вы можете хранить их как int unsigned и использовать функции INET_ATON() и INET_NTOA() для возврата IP-адреса из его числового значения, и наоборот." Я думаю, это то, что я собираюсь использовать в своей базе данных, если только я не решу использовать функции php, упомянутые выше.