みんな--
私はこれについて少し混乱しています。 csplitを使用して複数の入力ファイルを取得し、同じパターンに従って分割するbashスクリプトを作成しようとしています。 (コンテキスト:\questionコマンドで区切られた質問を含むTeXファイルが複数あります。各質問を独自のファイルに抽出したいと思います。)
これまで私のコードは次のようになります。
#!/bin/bash
# This script uses csplit to run through an input TeX file (or list of TeX files) to separate out all the questions into their own files.
# This line is for the user to input the name of the file they need questions split from.
read -ep "Type the directory and/or name of the file needed to split. If there is more than one file, enter the files separated by a space. " files
read -ep "Type the directory where you would like to save the split files: " save
read -ep "What unit do these questions belong to?" unit
# This is a check for the user to confirm the file list, and proceed if true:
echo "The file(s) being split is/are $files. Please confirm that you wish to split this file, or cancel."
select ynf in "Yes" "No"; do
case $ynf in
No ) exit;;
Yes ) echo "The split files will be saved to $save. Please confirm that you wish to save the files here."
select ynd in "Yes" "No"; do
case $ynd in
Yes )
# This line will create a loop to conduct the script over all the files in the list.
for i in ${files[@]}
do
# Mass re-naming is formatted to give "guestion###.tex' to enable processing a large number of questions quickly.
# csplit is the utility used here; run "man csplit" to learn more of its functionality.
# the structure is "csplit [name of file] [output options] [search filter] [separator(s)].
# this script calls csplit, will accept the name of the file in the argument, searches the files for calls of "question", splits the file everywhere it finds a line with "question", and renames it according to the scheme [prefix]#[suffix] (the %03d in the suffix-format is what increments the numbering automatically).
# the '\\question' allows searching for \question, which eliminates the split for \end{questions}; eliminating the \begin{questions} split has not yet been understood.
csplit $i --prefix=$save'/'$unit'q' --suffix-format='%03d.tex' /'\\question'/ '{*}'
done; exit;;
No ) exit;;
esac
done
esac
done
return
入力ファイルに対して期待どおりに繰り返されることを確認できます。しかし、私が気づいた動作は、期待どおりに最初のファイルを「q1.tex q2.tex q3.tex」に分割し、リスト内の次のファイルに移動すると問題を分割して古いファイルを上書きすることです。 3番目のファイルは2番目のファイルの分割を上書きします。私が望むのは、File1に3つの問題がある場合は、次のように出力されることです。
q1.tex
q2.tex
q3.tex
その後、File2に4つの問題がある場合は、次のように増えます。
q4.tex
q5.tex
q6.tex
q7.tex
csplitがこのループで完了した数を検出して適切に増やす方法はありますか?
誰もが提供できる助けに感謝します!
答え1
このcsplit
コマンドはコンテキストを保存せず、保存もしないので、常に1から計算を開始します。この問題を回避する方法はありませんが、プレフィックス文字列に挿入された数値を保持できます。
または交換してみてください。
read -ep "Type the directory and/or name of the file needed to split. If there is more than one file, enter the files separated by a space. " files
...
for i in ${files[@]}
do
csplit $i --prefix=$save'/'$unit'q' --suffix-format='%03d.tex' /'\\question'/ '{*}'
done
そして
read -a files -ep 'Type the directory and/or name of the file needed to split. If there is more than one file, enter the files separated by a space. '
...
cat "${files[@]}" | csplit - --prefix="$save/${unit}q" --suffix-format='%03d.tex' '/\\question/' '{*}'
これは、実際にはファイル引数のみをcat {file} | ...
使用して使用する必要がある比較的まれなケースの1つです(またはcsplit
-
標準入力)。
ループでread
配列変数を(正しく)使用したいので、配列変数を使用するように操作を変更しました。for ... do csplit ...
最終的にどんな決定を下しても、すべての変数、特に配列のリスト(例:"${files[@]}"
。
答え2
Awkでは、次のことができます。
awk '/\\question/ {i++} ; {print > "q" i ".tex"}' exam*.tex
out-dir(d) と topic(t) を定義し、番号の長さを制御するには、次のようにします。
awk '/\\question/ {f=sprintf("%s/%s-q%03d.tex", d, t, i++)} {print>f}' d=d1 t=t1 ex*
TeX preambuloをスキップするには、「f」を定義するときに「印刷」できます。
awk '/\\question/ {f=sprintf("%s/%s-q%03d.tex", d, t, ++i)}
f {print>f}' d=d1 t=t1 ex*
答え3
このスクリプトを使用できます
grep -o -P '(parameter).*(parameter)' your_teX_file.teX > questions.txt
すべての質問を含むファイルを受け取り、questions.txt
それらを分割できます。
split -l 1 questions.txt