Перегляньте файл і надрукуйте текст із певних рядків


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

Чи можливо це? Я хочу встановити лінію і від позиції до цієї позиції.

Відповіді:


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робить), і буде відповідати 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-го.


1

підхід:

$ 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.