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

這可能嗎?我想設置線以及從位置到這個位置。

答案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 個字元。

第二個命令的整體思路相同,只是它只在第三行 ( 3s) 上運行,並且保留從第四行開始的 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到每一行。該腳本的基本思想與以前相同。該$.變數保存當前行號,因此我們檢查行號是否為13,如果因此,運行替換,否則跳過,因此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第一行從 ) 開始計數,第三行從 3-7 開始計數。

答案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

$ 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

這使用<shell 運算子將輸入流從輸入檔案重定向到 python 進程。請注意,python 中的字串是從 0 索引的,因此您需要將所需的字元數全部移 1。

便攜式外殼方式

這適用於ksh, dash, bash。僅依賴 shell 實用程序,不依賴任何外部工具。

#!/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

相關內容