나는 ~ 23000 라인의 SQL 덤프를 가지고있다. 이 파일의 특정 섹션 (즉, 단일 데이터베이스에 대한 데이터)을 추출하여 새 파일에 배치해야합니다. 내가 원하는 데이터의 시작과 끝 줄 번호를 모두 알고 있습니다.
누구든지 16224와 16482 라인 사이의 파일에서 모든 라인을 추출한 다음 새로운 파일로 리디렉션하는 유닉스 명령 (또는 일련의 명령)을 알고 있습니까?
sed -n '16224,16482p;16483q' filename > newfile
sed 매뉴얼 :
p - (표준 출력으로) 패턴 공간을 출력하십시오. 이 명령은 일반적으로 -n 명령 줄 옵션과 함께 만 사용됩니다.
n - 자동 인쇄가 비활성화되어 있지 않으면 패턴 공간을 인쇄 한 다음에 관계없이 패턴 공간을 다음 입력 줄로 바꿉니다. 더 이상 입력이 없으면 sed는 더 이상 명령을 처리하지 않고 종료합니다.
q - 더 이상 명령이나 입력을 처리하지 않고
sed
을 종료합니다. -n 옵션을 사용하여 자동 인쇄를 비활성화하지 않으면 현재 패턴 공간이 인쇄됩니다.
Sed 스크립트의 주소는 다음 형식 중 하나 일 수 있습니다.
number 행 번호를 지정하면 입력의 해당 행과 만 일치합니다.
주소 범위는 쉼표 (,)로 구분 된 두 개의 주소를 지정하여 지정할 수 있습니다. 주소 범위는 첫 번째 주소가 일치하는 곳에서 시작하는 줄과 일치하고 두 번째 주소가 일치 할 때까지 계속됩니다.
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
트릭을해야합니다. 이 방법의 단점은 꼬리에 대한 인수를 결정하고 '사이에'에 끝 줄을 포함 시킬지 여부를 설명하기 위해 산술을 수행해야한다는 것입니다.
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.
나는 이것을 정확하게 수행하는 splitter 라는 Haskell 프로그램을 작성했습니다 : 내 릴리스 블로그 게시물을 읽음 .
다음과 같이 프로그램을 사용할 수 있습니다.
$ cat somefile | splitter 16224-16482
그리고 그것이 전부입니다. Haskell을 설치해야합니다. 다만:
$ cabal install splitter
그리고 당신은 끝났습니다. 이 프로그램이 도움이 되길 바랍니다.
나는 머리/꼬리 트릭을 게시하려했으나 실제로는 이맥스를 발사 할 것입니다. ;-)
새로운 출력 파일을 열어 ctl-y save
무슨 일이 일어나는지 보자.
cat filename|sed 'n1,n2!d' > abc.txt
For Example:
cat foo.pl|sed '100,200!d' > abc.txt
Ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf
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.
awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt
FNR contains the record (line) number of the line being read from the file.
sed -ne '16224,16482w newfile' -e '16482q' file
or taking advantage of bash:
sed -n $'16224,16482w newfile\n16482q' file
.
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
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).
.
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
.
cat $filename | sed "${linenum}p;d";
This does the following: