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 文字目までのデータと、3 行目の 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スクリプトには2つのコマンドがあり、どちらも置換演算子(s/original/replacement/)を使用しています。 は1s/.{11}(.{8}).*/\1/p1行目のみで実行され( が行うことです1s)、行の最初の11文字(.{11})と一致し、その後キャプチャ次の 8 文字 ( (.{8})、括弧は「キャプチャ グループ」) と、行末 ( .*) までのその他すべての文字が続きます。これらすべてがキャプチャ グループ ( \1、2 番目のキャプチャ グループがある場合は、などになります\2) に置き換えられます。最後に、p末尾の ( s/foo/bar/p) により、置換が行われた後に行が印刷されます。この結果、対象の 8 文字のみが出力されます。

2 番目のコマンドは、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、「入力ファイルを 1 行ずつ読み取り、-e各行に で指定されたスクリプトを適用する」ことを意味します。スクリプトの基本的な考え方は前と同じです。変数には$.現在の行番号が保持されるため、行番号が または のどちらかであるかどうかを確認し13そうである場合は置換を実行し、そうでない場合はスキップします。したがって、 はprintこれら 2 行に対してのみ実行され、他の行はすべてスキップされます。


もちろんこれはPerlなのでティムトウトディ:

$ perl -F"" -lane '$. == 1 && print @F[11..19]; $.==3 && print @F[3..6]' file 
Ethernet 
t6 a

説明

ここで、 は-a「各入力行を で指定された文字で分割し-F、配列 として保存する」ことを意味します@F。指定された文字は空なので、入力行の各文字が の要素として保存されます。次に、 1 行目に要素 11 ~ 19 (配列は からカウントを開始します) を出力し、3 行目に要素 3 ~ 7 を@F出力します。0

答え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これは、、で動作しますdashbashシェル ユーティリティのみに依存し、外部には依存しません。

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

関連情報