подход awk:

подход awk:

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

Например, давайте возьмем такой пример 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-й символ третьей строки? Вывод будет выглядеть примерно так:

Ethernet
t6 ad

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

решение1

Вот 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будет работать только на первой строке (именно это и 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, так чтоТИМТОВТДИ:

$ 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-й.

решение2

подход 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

Связанный контент