Pythonрешение:
образец входного файлаtest.csv
:
A1,B1,C1,D1,E1,F1,A2,B2,C2,D2,E2,F2,A3,B3,C3,D3,E3,F3,A4,B4,C4,D4,E4,F4
G1,H1,I1,J1,K1,L1,G2,H2,I2,J2,K2,L2,G3,H3,I3,J3,K3,L3,G4,H4,I4,J4,K4,L4
фрагмент _на _6.pyскрипт:
import sys, csv
with open(sys.argv[1], 'r') as fh: # opening csv file
reader = list(csv.reader(fh)) # reader object which will iterate over lines in the given csvfile
cnt = len(reader[0])//6 # number(count) of slices
for i in range(cnt):
for l in reader:
print(','.join(l[i*6:6*(i+1)])) # outputting each slice from each line consecutively
Использование:
python slice_on_6.py test.csv
Выход:
A1,B1,C1,D1,E1,F1
G1,H1,I1,J1,K1,L1
A2,B2,C2,D2,E2,F2
G2,H2,I2,J2,K2,L2
A3,B3,C3,D3,E3,F3
G3,H3,I3,J3,K3,L3
A4,B4,C4,D4,E4,F4
G4,H4,I4,J4,K4,L4
Удалите ^
и $
из команды и используйте флаг -o
команды grep, т.е.:
grep -Eo '(^| )(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($|[[:space:]])'
Пример:
echo 'some text 198.54.34.6 and test' | grep -Eo '(^| )(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($|[[:space:]])'
вывод:
198.54.34.6
Это даст пробелы, также попробуйте удалить их, используя tr
, например command1 | tr -d " "
.
^
и $
совпадают соответственно в начале и конце строки, поэтому строки с этими IP-адресами совпадают только в том случае, если IP-адрес находится как в начале, так и в конце строки, то есть если IP-адрес — это вся строка.
Теперь, если вы хотите сопоставить строки, содержащие IP-адрес целиком слово , где слова пусты -с разделителями, вы можете использовать:
d='[01234567890]'
n="($d|[123456789]$d|1$d$d|2[01234]$d|25[012345])"
grep -E "(^|[[:blank:]])$n\.$n\.$n\.$n([[:blank:]]|\$)" ip.txt
(здесь также замена [0-9]
на [0123456789]
, поскольку [0-9]
часто соответствует гораздо большему, чем просто 0123456789 ).
Обратите внимание, что grep
выводит совпадающие строки . Если вы хотите выводить только части строк, вам нужно использовать такие вещи, как sed
или perl
вместо (потоковых редакторов ), или использовать некоторые не -стандартные расширения некоторых grep
реализации, такие как -o
GNU grep
.
Здесь используется отрицательный взгляд -вокруг операторов ((?<!\H)
, что означает «при условии, что ему не предшествует не -пробел» , (?!\H)
то же самое, но взгляд вперед, а не назад, (?1)
вызывает RE в первой группе (...)
, все perl -подобные операторы включены с-P
:
grep -Po '(?<!\H)(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.(?1)\.(?1)\.(?1)(?!\H)' ip.txt
Что было бы эквивалентно:
perl -lne 'print for
/(?<!\H)(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.(?1)\.(?1)\.(?1)(?!\H)/g'
Это регулярное выражение захватывает IP-адрес и является довольно точным регулярным выражением для IPv4-адресов, grep -P
включает механизм регулярных выражений PCRE и -o
возвращает только соответствующий текст:
grep -Po '\b((?:25[0-5]|[2][0-4][0-9]|[1][0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|[2][0-4][0-9]|[1][0-9]{2}|[1-9][0-9]|[0-9])\b' ip.txt
Объяснение этого регулярного выражения см. здесь:https://regexr.com/4kjg4
25[0-5] | # 250 - 255
[2][0-4][0-9] | # 200 - 249
[1][0-9]{2} | # 100 - 199
[1-9][0-9] | # 10 - 99
[0-9] | # 0 - 9
Чтобы распечатать только IPv4, вы можете извлечь то, что совпадает с опцией -o
для grep.
В качестве более простого примера вы можете сделать:
$ echo "this is a simple test to extract 123.234.34.5 as an IP" |
grep -o '[0-9.]*'
123.234.34.5
Но это не будет точно соответствовать одному IPv4.
Для сопоставления IP-адреса с регулярным выражением несколько сложно. Регулярное выражение не понимает числовые диапазоны, только текст. Мы можем сопоставить одно числовое значение 0 -255 с (регулярным выражением, которое игнорирует пробелы и комментарии):
25[012345] | # the numers 250 - 255 or
2[01234](?P<digit>[0123456789]) | # 200 - 249 or
1(?&digit){2} | # 100 - 199 or
#0? # Allow leading zero
[1-9](?&digit) | # 10 - 99 or
#0{0,2} # Allow leading zeros
(?&digit) # 0 - 9
Удалите комментарии к первому столбцу, чтобы включить ведущие нули.
Чтобы избежать повторения [0-9]
, использовать явные числовые диапазоны (, избегать сопоставления чисел на других языках )и давать имя каждой совпадающей группе, мы можем использовать «Именованные группы захвата» из PCRE :
(?P<byte> # Define this as one full byte value.
25[012345] | # the numers 250 - 255 or
2[01234](?P<digit>[0123456789]) | # 200 - 249 or
1(?&digit){2} | # 100 - 199 or
#0? # Allow leading zero
[1-9](?&digit) | # 10 - 99 or
#0{0,2} # Allow leading zeros
(?&digit) # 0 - 9
) # close one full byte definition
Затем нам просто нужно повторить использование определения байта с ведущей точкой (\.(?&byte)){3}
еще три раза и некоторыми начальными и конечными маркерами, как показано в этой ссылке
Начальный и конечный маркеры могут быть более простыми «границами слов» (\b
), если это то, что необходимо, как показано в этой другой ссылке
В оболочке с регулярным выражением grep PCRE команда может быть записана как:
$ grep -oP '(?xm)(?<=^|[^01234567890.])(?P<byte>25[012345]|2[01234](?P<digit>[0123456789])|[01]?(?&digit){1,2})(\.(?&byte)){3}(?=[^01234567890.]|$)' <<<"$a"
1.2.3.4
11.22.33.44
123.234.34.5
1.1.192.168
123.234.34.123
123.234.34.123
1.2.3.255
255.255.255.255
1.1.168.192
1.14.2.90
1.2.3.4
Учитывая, что тестовая строка содержит:
$ a='1.2.3.4
11.22.33.44
123.234.34.5
1.1.192.168
text 123.234.34.123 more text
text123.234.34.123more text
1.2.3.255
1.2.3.256
255.255.255.255
256.2.3.4
1123.234.34.123
123.234.34.1235
.123.234.34.123
123.234.34.123.
not 1.1.168.192 in 1.1.168.192.in-addr.arpa.
not 1.14.2.90 in xserver-common_1.14.2.901-2_all.deb
1.2.3.4'