いくつかのデータベースに相当するデータを含む23000行までのSQLダンプがあります。このファイルの特定のセクション(つまり単一のデータベースのデータ)を抽出し、それを新しいファイルに配置する必要があります。必要なデータの開始行番号と終了行番号の両方を知っています。
16224行から16482行の間にあるファイルからすべての行を抽出し、それらを新しいファイルにリダイレクトするというUnixコマンド(または一連のコマンド)を知っている人はいますか?
sed -n '16224,16482p;16483q' filename > newfile
p - パターンスペースを(標準出力に)出力します。このコマンドは通常、-nコマンドラインオプションと組み合わせてのみ使用されます。
n - 自動印刷が無効になっていない場合は、パターンスペースを印刷してから、パターンスペースを次の入力行に置き換えます。それ以上入力がない場合、sedはそれ以上コマンドを処理せずに終了します。
q - これ以上コマンドや入力を処理せずに
sed
を終了します。自動印刷が-nオプションで無効にされていない場合、現在のパターンスペースが印刷されることに注意してください。
Sedスクリプトのアドレスは、次のいずれかの形式になります。
number 行番号を指定すると、入力内のその行だけに一致します。
アドレス範囲は、2つのアドレスをコンマ(、)で区切って指定することで指定できます。アドレス範囲は、最初のアドレスが一致する位置から始まる行に一致し、2番目のアドレスが一致するまで続きます。
sed -n '16224,16482 p' orig-data-file > new-file
16224、16482は開始行番号と終了行番号です(両端を含む)。これは1インデックスです。 -n
は、入力が出力としてエコーされるのを抑制します。数字は、次のコマンドを実行する行の範囲を示します。コマンドp
は関連する行を表示します。
頭と尾を使うのはとても簡単:
head -16482 in.sql | tail -258 > out.sql
sedを使う:
sed -n '16482,16482p' in.sql > out.sql
awkを使う:
awk 'NR>=10&&NR<=20' in.sql > out.sql
'vi'を使用してから次のコマンドを使用できます。
:16224,16482w!/tmp/some-file
あるいは
cat file | head -n 16482 | tail -n 258
編集: - 説明を加えるために、 head -n 16482 を使用して最初の16482行を表示し、次に tail -n 258 を使用して最初の出力から最後の258行を取り出します。
awk
には別のアプローチがあります。
awk 'NR==16224, NR==16482' file
ファイルが巨大な場合は、最後の目的の行を読んだ後でexit
を実行するのが良いでしょう。このように、それは不必要に以下の行を読みません:
awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file
Perl -ne 'print if 16224..16482' file.txt > new_file.txt
# print section of file based on line numbers
sed -n '16224 ,16482p' # method 1
sed '16224,16482!d' # method 2
sed -n '16224,16482p' < dump.sql
cat dump.txt | head -16224 | tail -258
トリックをするべきです。このアプローチの欠点は、tailの引数を決定し、 'between'に終了行を含めるかどうかを考慮するために算術演算を行う必要があることです。
早くて汚い:
head -16428 < file.in | tail -259 > file.out
おそらく最善の方法ではありませんが、うまくいくはずです。
BTW:259 = 16482-16224 + 1。
私はヘッド/テールトリックを投稿しようとしていましたが、実際には私はおそらく単にemacsを起動させるでしょう。 ;-)
新しい出力ファイルを開く、ctl-y save
何が起こっているのか見てみましょう。
コマンドラインで確認するためにこれを行うこともできます。
cat filename|sed 'n1,n2!d' > abc.txt
例えば:
cat foo.pl|sed '100,200!d' > abc.txt
Rubyを使う:
Ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf
Boxxarの肩の上に立って、私はこれが好きです:
sed -n '<first line>,$p;<last line>q' input
例えば.
sed -n '16224,$p;16482q' input
$
は "最後の行"を意味するので、最初のコマンドはsed
に行16224
で始まるすべての行を印刷させ、2番目のコマンドはsed
を after printing行16428
にします。 (boxxarのソリューションでq
- rangeに1
を追加する必要はないようです。)
終了行番号を2回指定する必要がないので、この方法が好きです。そして私は、$
を使用してもパフォーマンスに悪影響がないことを測定しました。
私は使うだろう:
awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt
FNRには、ファイルから読み取られている行のレコード(行)番号が含まれています。
これはうまくいくかもしれません(GNU sed)。
sed -ne '16224,16482w newfile' -e '16482q' file
またはbashを利用する:
sed -n $'16224,16482w newfile\n16482q' file
PATHをそのディレクトリを含むように更新する限り(またはPATHに既に含まれているディレクトリに置くことができる限り)、コマンドラインから実行できる小さなbashスクリプトを書きました。
使用法:$ pinchファイル名開始行終了行
#!/bin/bash
# Display line number ranges of a file to the terminal.
# Usage: $ pinch filename start-line end-line
# By Evan J. Coon
FILENAME=$1
START=$2
END=$3
ERROR="[PINCH ERROR]"
# Check that the number of arguments is 3
if [ $# -lt 3 ]; then
echo "$ERROR Need three arguments: Filename Start-line End-line"
exit 1
fi
# Check that the file exists.
if [ ! -f "$FILENAME" ]; then
echo -e "$ERROR File does not exist. \n\t$FILENAME"
exit 1
fi
# Check that start-line is not greater than end-line
if [ "$START" -gt "$END" ]; then
echo -e "$ERROR Start line is greater than End line."
exit 1
fi
# Check that start-line is positive.
if [ "$START" -lt 0 ]; then
echo -e "$ERROR Start line is less than 0."
exit 1
fi
# Check that end-line is positive.
if [ "$END" -lt 0 ]; then
echo -e "$ERROR End line is less than 0."
exit 1
fi
NUMOFLINES=$(wc -l < "$FILENAME")
# Check that end-line is not greater than the number of lines in the file.
if [ "$END" -gt "$NUMOFLINES" ]; then
echo -e "$ERROR End line is greater than number of lines in file."
exit 1
fi
# The distance from the end of the file to end-line
ENDDIFF=$(( NUMOFLINES - END ))
# For larger files, this will run more quickly. If the distance from the
# end of the file to the end-line is less than the distance from the
# start of the file to the start-line, then start pinching from the
# bottom as opposed to the top.
if [ "$START" -lt "$ENDDIFF" ]; then
< "$FILENAME" head -n $END | tail -n +$START
else
< "$FILENAME" tail -n +$START | head -n $(( END-START+1 ))
fi
# Success
exit 0
私は変数を使ってスクリプトから同じことをしたいと思っていて、pから変数名を分けるために$変数を囲むことによってそれを達成しました:
sed -n "$first","$count"p imagelist.txt >"$imageblock"
リストを別々のフォルダに分割して、最初の質問を見つけて便利な手順に答えたかったのです。 (splitコマンドは私がコードを移植しなければならない古いOS上のオプションではありません)。
テキストファイルからテキストの行を抽出する方法について説明しているので、特定のパターンに一致するすべての行を抽出するという特別な場合を挙げます。
myfile content:
=====================
line1 not needed
line2 also discarded
[Data]
first data line
second data line
=====================
sed -n '/Data/,$p' myfile
[Data]行と残りを印刷します。 line1からパターンまでのテキストが必要な場合は、次のように入力します。sed -n '1、/ Data/p' myfile。さらに、2つのパターンがわかっている場合(テキスト内で一意であることが望ましい)、範囲の開始行と終了行の両方をmatchで指定できます。
sed -n '/BEGIN_MARK/,/END_MARK/p' myfile
Accept answerの-nは機能します。あなたが傾いている場合に備えて、これは別の方法です。
cat $filename | sed "${linenum}p;d";
これにより、次のことが行われます。