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

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

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

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

8
задан 5 November 2017 в 07:15

2 ответа

Вот 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-го.

9
ответ дан 5 November 2017 в 07:15
  • 1
    @matohak я на самом деле открыл Konqueror и затем использовал Файл - Открытый... – andrew.46 20 October 2018 в 21:42

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

$ 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
1
ответ дан 23 November 2019 в 05:38

Другие вопросы по тегам:

Похожие вопросы: