保存したデータを含むファイルがあります。結果を新しいファイルに印刷したいと思います。
たとえば、次の例を見てみましょう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/p
1行目のみで実行され( が行うことです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
各行に で指定されたスクリプトを適用する」ことを意味します。スクリプトの基本的な考え方は前と同じです。変数には$.
現在の行番号が保持されるため、行番号が または のどちらかであるかどうかを確認し1
、3
そうである場合は置換を実行し、そうでない場合はスキップします。したがって、 は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
これは、、で動作します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