it-swarm-ko.tech

유닉스의 텍스트 파일에서 미리 지정된 범위의 행을 어떻게 추출 할 수 있습니까?

나는 ~ 23000 라인의 SQL 덤프를 가지고있다. 이 파일의 특정 섹션 (즉, 단일 데이터베이스에 대한 데이터)을 추출하여 새 파일에 배치해야합니다. 내가 원하는 데이터의 시작과 끝 줄 번호를 모두 알고 있습니다.

누구든지 16224와 16482 라인 사이의 파일에서 모든 라인을 추출한 다음 새로운 파일로 리디렉션하는 유닉스 명령 (또는 일련의 명령)을 알고 있습니까?

468
Adam J. Forster
sed -n '16224,16482p;16483q' filename > newfile

sed 매뉴얼 :

p - (표준 출력으로) 패턴 공간을 출력하십시오. 이 명령은 일반적으로 -n 명령 줄 옵션과 함께 만 사용됩니다.

n - 자동 인쇄가 비활성화되어 있지 않으면 패턴 공간을 인쇄 한 다음에 관계없이 패턴 공간을 다음 입력 줄로 바꿉니다. 더 이상 입력이 없으면 sed는 더 이상 명령을 처리하지 않고 종료합니다.

q - 더 이상 명령이나 입력을 처리하지 않고 sed을 종료합니다. -n 옵션을 사용하여 자동 인쇄를 비활성화하지 않으면 현재 패턴 공간이 인쇄됩니다.

Sed 스크립트의 주소는 다음 형식 중 하나 일 수 있습니다.

number 행 번호를 지정하면 입력의 해당 행과 만 일치합니다.

주소 범위는 쉼표 (,)로 구분 된 두 개의 주소를 지정하여 지정할 수 있습니다. 주소 범위는 첫 번째 주소가 일치하는 곳에서 시작하는 줄과 일치하고 두 번째 주소가 일치 할 때까지 계속됩니다.

703
boxxar
sed -n '16224,16482 p' orig-data-file > new-file

여기서 16224, 16482는 시작 행 번호와 끝 행 번호 (포함)입니다. 이것은 1 색인입니다. -n는 입력을 출력으로 울리는 것을 억제합니다. 숫자는 다음 명령이 작동하게하는 행의 범위를 나타냅니다. p 명령은 관련 행을 인쇄합니다.

195
JXG

머리/꼬리를 사용하여 매우 간단합니다.

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
81
manveru

'vi'를 사용하고 다음 명령을 사용할 수 있습니다.

:16224,16482w!/tmp/some-file

대안 :

cat file | head -n 16482 | tail -n 258

편집 : - 단지 설명을 추가하려면 head -n 16482 를 사용하여 처음 16482 줄을 표시 한 다음 tail -n 258 을 사용하여 첫 번째 출력에서 ​​마지막 258 줄을 가져옵니다.

26
Mark Janssen

awk에는 또 다른 접근법이 있습니다.

awk 'NR==16224, NR==16482' file

파일이 크면 마지막 원하는 행을 읽은 후 exit에 적합 할 수 있습니다. 이렇게하면 불필요하게 다음 줄을 읽지 않습니다.

awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file
24
fedorqui
Perl -ne 'print if 16224..16482' file.txt > new_file.txt
17
mmaibaum
 # print section of file based on line numbers
 sed -n '16224 ,16482p'               # method 1
 sed '16224,16482!d'                 # method 2
8
Cetra

sed -n '16224,16482p' < dump.sql

5
cubex
cat dump.txt | head -16224 | tail -258

트릭을해야합니다. 이 방법의 단점은 꼬리에 대한 인수를 결정하고 '사이에'에 끝 줄을 포함 시킬지 여부를 설명하기 위해 산술을 수행해야한다는 것입니다.

5
JP Lodine

head -16428 < file.in | tail -259 > file.out

Probably not the best way to do it but it should work.

BTW: 259 = 16482-16224+1.

3
jan.vdbergh

나는 이것을 정확하게 수행하는 splitter 라는 Haskell 프로그램을 작성했습니다 : 내 릴리스 블로그 게시물을 읽음 .

다음과 같이 프로그램을 사용할 수 있습니다.

$ cat somefile | splitter 16224-16482

그리고 그것이 전부입니다. Haskell을 설치해야합니다. 다만:

$ cabal install splitter

그리고 당신은 끝났습니다. 이 프로그램이 도움이 되길 바랍니다.

3
Robert Massaioli

나는 머리/꼬리 트릭을 게시하려했으나 실제로는 이맥스를 발사 할 것입니다. ;-)

  1. esc-x 고토 라인 ret 16224
  2. 표시 (ctrl-space)
  3. esc-x 고토 라인 ret 16482
  4. esc-w

새로운 출력 파일을 열어 ctl-y save

무슨 일이 일어나는지 보자.

3
sammyo

cat filename|sed 'n1,n2!d' > abc.txt

For Example:

cat foo.pl|sed '100,200!d' > abc.txt
2
Chinmoy Padhi

Ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf
2
Carl Blakeley

sed -n '<first line>,$p;<last line>q' input

e.g.

sed -n '16224,$p;16482q' input

The $ means "last line", so the first command makes sed print all lines starting with line 16224 and the second command makes sed quit after printing line 16428. (Adding 1 for the q-range in boxxar's solution does not seem to be necessary.)

I like this variant because I don't need to specify the ending line number twice. And I measured that using $ does not have detrimental effects on performance.

2
Tilman Vogel

awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt

FNR contains the record (line) number of the line being read from the file.

2
Paddy3118

sed -ne '16224,16482w newfile' -e '16482q' file

or taking advantage of bash:

sed -n $'16224,16482w newfile\n16482q' file
1
potong

.

Usage: $ pinch filename start-line end-line

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

sed -n "$first","$count"p imagelist.txt >"$imageblock"

I wanted to split a list into separate folders and found the initial question and answer a useful step. (split command not an option on the old os I have to port code to).

1
KevinY

.

myfile content:
=====================
line1 not needed
line2 also discarded
[Data]
first data line
second data line
=====================
sed -n '/Data/,$p' myfile

Will print the [Data] line and the remaining. If you want the text from line1 to the pattern, you type: sed -n '1,/Data/p' myfile. Furthermore, if you know two pattern (better be unique in your text), both the beginning and end line of the range can be specified with matches.

sed -n '/BEGIN_MARK/,/END_MARK/p' myfile
0
Kemin Zhou

.

cat $filename | sed "${linenum}p;d";

This does the following:

  1. pipe in the contents of a file (or feed in the text however you want).
  2. sed selects the given line, prints it
  3. d is required to delete lines, otherwise sed will assume all lines will eventually be printed. i.e., without the d, you will get all lines printed by the selected line printed twice because you have the ${linenum}p part asking for it to be printed. I'm pretty sure the -n is basically doing the same thing as the d here.
0
ThinkBonobo