印刷方法そして前の行後ろに並ぶ3行目

印刷方法そして前の行後ろに並ぶ3行目

質問ここパターンマッチングの前後に数行の入力が必要です。

しかし、ここでの目標は行番号を取得し、ファイルから行番号の前後のいくつかの行を取得することです。

たとえば、

seq 10
1
2
3
4
5
6
7
8
9
10

行番号が6の場合は、行の前に4桁、行の後に3桁を入力する必要があります。それは

2
3
4
5
6
7
8
9

答え1

z=6   # focus line
x=4   # lines before
y=3   # lines after

start=$(( z - x ))
end=$(( z + y ))

使用sed:

seq 10 | sed -n "$start,${end}p"
2
3
4
5
6
7
8
9

これは明示的な行範囲を印刷するためにprint(p)コマンドを使用します。sed別の行を無視してください-n

使用awk:

seq 10 | awk -v start="$start" -v end="$end" 'NR >= start { print } NR >= end { exit }'
2
3
4
5
6
7
8
9

これはStéphane Chazelasの答えと似ていますが、awk;で実装されたスクリプトはstart行数を読み取った後に入力行の出力を開始します。行番号でendスクリプトが終了します。

xどちらの選択肢も、lineの前の行から始まり、lineの後の行で終わる入力データの一部を表示しますzyz

答え2

POSIXシェルの使用:

$ before=4 after=3 line=6
$ seq 10 | sed "$((line-before)),\$!d; $((line+after))q"
2
3
4
5
6
7
8
9

次のように翻訳されました:

  • D!()を除いて、範囲からすべての行を削除します。わかった - 前に最後の項目から最初の項目($)。
  • キュー適合行の後 +3行目

これにより、過去の内容をあえて読む必要がなくなります。行の後 +1行目。

しかし、これは、sedコマンドがデータ転送の直後にデータを送信し続ける場合、SIGPIPE を介してコマンドが中断され、これは望むかもしれないし、望ましくないかもしれないことを意味します。

答え3

完全性のために:

$ l=60;seq 100 |head -n$((l+3)) |tail -n+$((l-4))
56
57
58
59
60
61
62
63

噂と様々なベンチマークによると、頭と尾の組み合わせは他のツールよりはるかに高速です。

$ a=1000000000
$ time seq $a |awk 'NR>=499998{print}NR >= 500004 { exit }' 
499998
499999
500000
500001
500002
500003

real    0m0.158s
user    0m0.152s
sys 0m0.004s

$ time seq $a |sed -n "499998,500003p"
499998
499999
500000
500001
500002
500003

real    1m30.249s
user    1m21.284s
sys 0m12.312s

$ time seq $a |sed "$((500000-2)),\$!d; $((500000+3))q"  #Stephan's Solution
499998
499999
500000
500001
500002
500003

real    0m0.052s
user    0m0.044s
sys 0m0.004s

$ time seq $a |head -n$((500000+3)) |tail -n+$((500000-2))
499998
499999
500000
500001
500002
500003

real    0m0.024s
user    0m0.024s
sys 0m0.004s

$ time seq $a |sed -n "499998,500003p;500004q"
499998
499999
500000
500001
500002
500003

real    0m0.056s
user    0m0.048s
sys 0m0.004s

答え4

# define line range constants
before=4
  line=6
 after=3

# setup the sed commands s.t. pattern space holds $before number
# of lines before we hit the line number $line and $after after
s='$!N'
p=`seq -s "$s"   "$before"`
a=`seq -s "$s" 0 "$after"`

N=${p//[0-9]/;}
n=${a//[0-9]/;}

# main...
seq 10 |
sed -e "
   1{ $N }
   \$d;N
   $line!D
   $n;q
"

もう1つの方法は、ファイルを読み込み、フィールド(現在の行)がになるようにFS設定することです。残りは行6と前後の4つの要素を切り取ることです。\n@F

perl -alF\\n -0777ne '$,=$\;print @F[6-4-1..6+3-1]' yourfile

結果

2
3
4
5
6
7
8
9

関連情報