그래서 나한테는테마 폴더여기에는 다음 주제가 포함되어 있습니다.
- 지리학
- 수학
이러한 주제는 파일입니다. 각 시트에는 학생의 이름과 점수가 포함되어 있습니다.
예를 들어,
지리학을 위해
- 마태복음 15장
- 엘레나 14
그리고 수학:
- 마태복음 10장
- 엘레나 19
나도 하나 갖고 있어학생 폴더현재는 비어 있습니다. 이 폴더의 목적은 다음을 넣는 것입니다.
- 파일 이름으로 학생 이름;
- 모든 과목에서 학생이 획득한 점수입니다.
그럼 이게 내 코드야:
#### Subjects folder #####
GEOGRAPHY="/home/subject/geography"
MATH="/home/subject/math"
##### Registration student #####
studentMatthew="/home/student/Matthew"
Geo_Matthew=$(grep "Matthew" "$GEOGRAPHY" | cut -d' ' -f2) > "$studentMatthew"
Math_Matthew=$(grep "Matthew" "$MATH" | cut -d' ' -f2) > "$studentMatthew"
studentElena="/home/student/Elena"
Geo_Elena=$(grep "Elena" "$GEOGRAPHY" | cut -d' ' -f2) > "$studentElena"
Math_Elena=$(grep "Elena" "$MATH" | cut -d' ' -f2) > "$studentElena"
##### SHOW RESULT #####
echo "Geography" >> "$studentMatthew" "$Geo_Matthew"
echo "Math" >> "$studentMatthew" "$Geo_Matthew"
echo "Geography" >> "$studentElena" "$Geo_Elena"
echo "Math" >> "$studentElena" "$Math_Elena"
이것은 매우 잘 작동합니다. 하지만 이런 식으로 글을 쓰는 것은 좋은 생각이 아닙니다.
왜냐면 제가 또 다른 학생을 추가한다면, Patrick이라고 말해주세요.수동지리와 수학 점수를 더하세요.
그래서 그것은 다음과 같습니다:
##### Registration Patrick #####
studentPatrick="/home/student/Patrick"
Geo_Patrick=$(grep "Patrick" "$GEOGRAPHY" | cut -d' ' -f2) > "$studentPatrick"
Math_Patrick=$(grep "Patrick" "$MATH" | cut -d' ' -f2) > "$studentPatrick"
##### SHOW RESULT PATRICK #####
echo "Geography" >> "$studentPatrick" "$Geo_Patrick"
echo "Math" >> "$studentPatrick" "$Math_Patrick"
그리고 그것은 매우 중복 될 것입니다 ...
그래서 나는 알고 싶다.
이 코드를 루프로 리팩터링할 수 있는 방법이 있나요? 그러면 새 학생을 추가하면 다시 수동으로 작성할 필요가 없나요?
답변1
for subjfile in /home/subject/*; do
awk -v subj="$(basename "$subjfile")" '{ print subj, $2 >>"/home/student/" $1 }' "$subjfile"
done
이는 모든 테마 파일을 반복합니다. 값 은 사용 가능한 테마에 따라 등이 될 $subjfile
수 있습니다 ./home/subject/Math
/home/subject/Geography
프로그램은 awk
차례로 각 파일을 열고 주제 이름(예 $subjfile
: Math
경로 이름의 "basename" Geography
)과 해당 주제의 태그( $subjfile
파일의 열 2)를 인쇄합니다.
"/home/student/" $1
이는 가 있는 경로 이름 에 기록됩니다 /home/student
. $1
예첫 번째파일의 열은 $subjfile
학생의 이름입니다.
이 코드는 student
스크립트가 실행되기 시작할 때 디렉터리가 비어 있다고 가정합니다(또는 스크립트가 디렉터리에 파일을 추가할 것이라고 가정합니다).
주어진 데이터(이름 중 하나의 철자 오류 포함)를 실행하면 다음 위치에 세 개의 파일이 생성됩니다 /home/student
.
$ cat Elena
Geography 14
Math 19
$ cat Mattew
Geography 15
$ cat Matthew
Math 10
학생 이름은 아래 파일에서 선택되며 /home/subject
스크립트에 하드코딩되지 않습니다. 또한 다양한 테마는 /home/subject
디렉토리에서 사용 가능한 파일에 따라 달라집니다.
다음을 건드리지 않고 이 작업을 수행하시겠습니까 awk
?
for subjfile in /home/subject/*; do
subject=$( basename "$subjfile" )
while read -r name marks; do
printf '%s %d\n' "$subject" "$marks" >>"/home/student/$name"
done <"$subjfile"
done
답변2
내 생각에 당신은 다음과 같은 일을 했습니다.
# loop over all files in the student directory
for studentfile in /home/student/*; do
# take just the name of the student (the file name without the path)
studentname="${studentfile##*/}"
# uncomment the next line to clear the student files before populating them
# > "$studentfile"
# loop over all subject files
for subject in /home/subject/*; do
# again, remove the path
subject="${subject##*/}"
grep "$studentname" "$subject" | cut -d' ' -f2 >> "$studentfile"
done
done
학생과 과목의 파일 이름이 파일에서 사용된 레이블과 정확히 동일하고 각 학생에 대한 파일이 이미 존재한다고 가정합니다.
확장은 가장 긴 접두사 일치 항목이 제거된 값을 사용합니다 ${var##*/}
. 즉, 경로만 남깁니다. 학생의 경우 출력 리디렉션에만 사용하므로 둘 다 필요합니다.$var
*/
Matthew
grep
/home/student/Matthew
Geo_Matthew=$(grep "Matthew" "$GEOGRAPHY" | cut -d' ' -f2) > "$studentMatthew"
작업에 출력을 생성하지 않는 추가 리디렉션이 있으므로 리디렉션은 출력 $studentMatthew
을 grep
파일로 리디렉션하고 명령 대체, 변수 Geo_Matthew
및 다음을 제거하기만 하면 됩니다 echo
.
쉘 스크립트 대신 awk 또는 Perl 스크립트를 사용하는 것이 더 좋지만 위의 방법은 루프에서 명령을 예약하는 가능한 방법입니다.