У меня есть файл с данными, которые я сохраняю. Теперь я хотел бы распечатать результаты в новом файле.
Например, давайте возьмем этот пример, randomlog.log
:
Link encap:Ethernet HWaddr 08:00:00:00:00:67
inet addr:10.10.10.10 Bcast:10.10.10.10 Mask:255.255.255.0
inet6 addr: fe80::casf:sdfg:23ra:dg12/64 Scope:Link
Как я могу взять только данные с 12-го по 20-й символ первой строки и затем с 4-го по 8-й символ 3-я строка? Вывод будет выглядеть примерно так:
Ethernet
t6 ad
Возможно ли это? Я хочу установить линию и из позиции в эту позицию.
Вот a sed
подход:
$ sed -nE '1s/.{11}(.{8}).*/\1/p; 3s/.{3}(.{4}).*/\1/p' file
Ethernet
t6 a
-n
подавляет нормальный вывод (нормальный, должен распечатать каждую входную строку) так, чтобы это только распечатало при сообщении. -E
включает расширенные регулярные выражения.
sed
сценарий имеет две команды, оба использования оператора замены (s/original/replacement/
). 1s/.{11}(.{8}).*/\1/p
будет только работать на 1-й строке (это что 1s
делает), и будет соответствовать 1-м 11 символам строки (.{11}
), затем это получает следующие 8 ((.{8})
, круглые скобки являются "группой получения") и затем все остальное до конца строки (.*
). Все это заменяется тем, что было в группе получения (\1
; если бы была вторая группа получения, то это было бы \2
и т.д.). Наконец, p
в конце (s/foo/bar/p
) заставляет строку быть распечатанной после того, как замена была сделана. Это приводит только к цели 8 производимых символов.
Вторая команда является тем же общим представлением за исключением того, что это будет только работать на 3-й строке (3s
) и сохранит эти 4 символа, начинающие с 4-го.
Вы могли также сделать то же самое с perl
:
$ perl -ne 'if($.==1){s/.{11}(.{8}).*/\1/}
elsif($.==3){s/.{3}(.{4}).*/\1/}
else{next}; print; ' file
Ethernet
t6 a
-ne
означает, "читает входной файл линию за линией и применяют сценарий, данный -e
к каждой строке. Сценарий является той же основной идеей как прежде. $.
переменная содержит текущий номер строки, таким образом, мы проверяем, также ли номер строки 1
или 3
и, если так, выполните замену, еще пропустите. Поэтому print
будет только выполнен для тех двух строк, так как все другие будут пропущены.
Конечно, это - Perl, таким образом, TIMTOWTDI:
$ perl -F"" -lane '$. == 1 && print @F[11..19]; $.==3 && print @F[3..6]' file
Ethernet
t6 a
Здесь, -a
означает, "разделяет каждую входную строку на символе, данном -F
и сохраните как массив @F
. Так как данный символ пуст, это сохранит каждый символ входной строки как элемент в @F
. Затем мы печатаем элементы 11-19 (массивы начинают рассчитывать в 0
) для 1-й строки и 3-7 для 3-го.
$ awk 'NR==1{print substr($0,12,8)};NR==3{print substr($0,4,4)}' input.txt
Ethernet
t6 a
Использование NR
для определения строки (в awk терминологии - запись) число, и соответственно печатают подстроку строки. substr()
функция находится в формате
substr(string,starting position,how much offset)
$ python -c 'import sys
> for index,line in enumerate(sys.stdin,1):
> if index == 1:
> print line[11:19]
> if index == 3:
> print line[3:7]' < input.txt
Ethernet
t6 a
Это использует <
оператор оболочки для перенаправления входного потока к Python обрабатывает из входного файла. Обратите внимание, что строки в Python 0-индексируемы, следовательно необходимо сместить числа требуемого символа все на 1.
Это работает в ksh
, dash
, bash
. Полагается только на утилиты оболочки, ничто внешнее.
#!/bin/sh
rsubstr(){
i=0;
while [ $i -lt $2 ];
do
rmcount="${rmcount}?"
i=$(($i+1))
done;
echo "${1#$rmcount}"
}
lsubstr(){
printf "%.${2}s\n" "$1"
}
line_handler(){
case $2 in
1) lsubstr "$(rsubstr "$1" 11)" 8 ;;
3) lsubstr "$(rsubstr "$1" 3)" 5 ;;
esac
}
readlines(){
line_count=1
while IFS= read -r line;
do
line_handler "$line" "$line_count"
line_count=$(($line_count+1))
done < $1
}
readlines "$1"
И это работает как так:
$ ./get_line_substrings.sh input.txt
Ethernet
t6 ad