Просмотреть файл и напечатать текст из определенных строк

8

У меня есть файл с данными, которые я сохраняю. Теперь я хотел бы распечатать свои результаты в новый файл.

Например, давайте возьмем этот пример 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

Это возможно? Я хочу установить линию и из позиции в эту позицию.

Insanebench420
источник

Ответы:

9

Вот 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делает) и будет соответствовать первым 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-й.

terdon
источник
1

awk подход:

$ 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
Сергей Колодяжный
источник