나는 수만 개의 디렉토리를 가지고 있습니다. 각 디렉터리의 이름은 숫자로 지정됩니다. 예를 들어 1, 2, 3,...
각 디렉터리에는 라는 큰 .dat 파일이 포함되어 있으며 data.dat
, 각 파일에는 다음과 같은 섹션이 있습니다.
Configurations for Sm:
Sm Nd H O
0 1 4 0 1.00 7.14%
1 0 3 0 3.00 7.14%
0 0 5 0 1.00 7.14%
각 행의 처음 두 숫자에 관심이 있습니다. 제 생각에는:
- 로 시작하는 모든 줄(이 경우 숫자의 첫 번째 줄)은
0 1
해당 줄로 시작하는 파일 이름(번호)으로 명명된 새 파일로 끝납니다.0-1.dat
아래는 "예제"라고 불리는 예입니다. - 마찬가지로 (여기서는 두 번째 줄)로 시작하는 모든 줄은
1 0
해당 줄의 시작 부분에 있는 파일 번호로 호출되는 파일로 끝나야 합니다.1-0.dat
- (여기서는 세 번째 줄)로 시작하는 모든 줄은
0 0
이름이 지정된 줄로 이동해야 합니다0-0.dat
.
필요한 라인을 찾는 복잡성은 다음과 같습니다.
- 경우에 따라 행 중 하나가 누락되거나 행 순서가 다를 수 있습니다.
- 또한 각 파일에는 이라는 이름의 여러 섹션이 있습니다
Configurations for X
. 여기서 X는 문자열입니다. 따라서 어떻게든 식별자를 사용Configurations for Sm:
하고 그 아래의 첫 번째 숫자 집합을 검색해야 합니다.
내가 달성하고자 하는 것의 예에서 줄의 첫 번째 숫자는 줄이 추출된 파일이 포함된 디렉터리 이름/번호입니다.
Example
In file called 0-1.txt:
1 0 1 4 0 1.00 7.14%
2 0 1 7 1 1.00 7.14%
3 0 1 ....
In file called 1-0.txt:
1 1 0 1 0 1.00 7.14%
2 1 0 4 2 1.00 7.14%
3 1 0 ....
나는 현재 다음을 가지고 있습니다:
find . -name data.dat -exec grep "Configurations for Sm:" {} + > 0-1.txt
하지만 이 모든 작업은 그 뒤에 오는 내용을 Configurations for Sm:
별도의 파일에 저장하는 것뿐입니다. 내가 해야 할 일을 어떻게 해야 할지 모르겠습니다. Configurations for Sm:
숫자 내용으로 아래 행을 찾으세요. 누구든지 팁이 있거나 저를 온라인 리소스로 안내해 주시면 매우 감사하겠습니다. 감사해요.
답변1
sed
와 를 조합해서 사용해도 될 것 같아요 grep
.
모든 디렉토리 0
, 1
, 2
,...가 다음 위치에 있다고 가정합니다 /your/path
(예 /your/path/0/data.dat
: ).
for dir in /your/path/*; do
idx=$(basename ${dir})
sed -n '/Configurations for Sm:/,/Configurations for/p' ${dir}/data.dat | \
grep '^ \+0 \+1' | \
sed "s/^/${idx}/" >> "0-1.dat"
done
첫 번째는 sed
파일의 흥미로운 부분(두 모드 Configurations for Sm:
와 모드 사이)만 추출해야 합니다.Configurations for
grep
줄의 시작 부분 과 일치합니다 0 1
(가운데에 양수 공백 포함).
두 번째 sed는 줄 시작 부분에 "index"(디렉토리 이름)를 추가합니다.
>>
출력은 "0-1.dat"에 추가됩니다( ).
0
다양한 합계 조합을 테스트하기 위해 외부 루프를 추가할 수 있습니다 1
.
참고: 나는 이것을 제대로 테스트하지 않았습니다.
답변2
awk
해결책은 어떻습니까?
awk '/^ *[0-1] +[0-1]/{
n=split(FILENAME,d,"/");print d[n-1], $0 > $1"-"$2".txt"
}' $(find . -name "*.dat")
먼저 find
모든 파일을 dat
제공하되 공백이 아닌 처음 2개의 문자로 awk
0 또는 1로 시작하는 행만 처리합니다.^
/^ *[0-1] +[0-1]/
그런 다음 split
파일 이름을 /
배열에 넣고 배열의 요소 수를n
n=split(FILENAME,d,"/")
마지막으로 디렉터리 이름/번호( d[n-1]
배열의 요소)와 dat
파일의 데이터를 $0
처음 두 값으로 구성된 파일로 인쇄합니다.
print d[n-1], $0 > $1"-"$2".txt"
수십 또는 수천 개의 파일이 있는 경우 한 줄당 오버헤드가 너무 클 split
수 있습니다 FILENAME
. 이 경우 각 파일을 반복하여 awk
정리된 파일에 추가 할 수 있습니다.>> $1"-"$2".txt"
아마도....
find . -iname "*.dat" -print0 | xargs -0 -n 1 -P 0 awk 'NR==1{n=split(FILENAME,d,"/"); dir=d[n-1]}/ *[0-1] +[0-1]/{print dir, $0 >> $1"-"$2".txt"}'