4

gnuplot を介してグラフを生成する bash に小さなスクリプトがあります。入力ファイルの名前にスペースが含まれるまで、すべてが正常に機能します。

これが私が持っているものです:

INPUTFILES=("data1.txt" "data2 with spaces.txt" "data3.txt")

...

#MAXROWS is set earlier, not relevant.


for LINE in $( seq 0 $(( MAXROWS - 1 )) );do

gnuplot << EOF
reset
set terminal png
set output "out/graf_${LINE}.png"

filenames="${INPUTFILES[@]}"

set multiplot 

plot for [file in filenames] file every ::0::${LINE} using 1:2 with line title "graf_${LINE}"

unset multiplot
EOF
done

このコードは機能しますが、入力ファイルの名前にスペースがない場合のみです。

gnuplot の例では、これを評価します。

1 iteration: file=data1.txt  - CORRECT
2 iteration: file=data2  - INCORRECT
3 iteration: file=with  - INCORRECT
4 iteration: file=spaces.txt  - INCORRECT
4

2 に答える 2

1

簡単に言えば、やりたいことを正確に行うことはできないということです。gnuplot は文字列をスペースの繰り返しで分割しますが、それを回避する方法はありません (AFIK)。あなたが望むものに応じて、「回避策」があるかもしれません。gnuplot で (再帰的な) 関数を記述して、文字列を別の文字列に置き換えることができます --

#S,C & R stand for STRING, CHARS and REPLACEMENT to help this be a little more legible.
replace(S,C,R)=(strstrt(S,C)) ? \
    replace( S[:strstrt(S,C)-1].R.S[strstrt(S,C)+strlen(C):] ,C,R) : S

再帰なしでこれを行う方法を理解できる人へのボーナスポイント...

次に、(bash) ループは次のようになります。

INPUTFILES_BEFORE=("data1.txt" "data2 with spaces.txt" "data3.txt")
INPUTFILES=()
#C style loop to avoid changing IFS -- Sorry SO doesn't like the #...
#This loop pre-processes files and changes spaces to '#_#'
for (( i=0; i < ${#INPUTFILES_BEFORE[@]}; i++)); do 
    FILE=${INPUTFILES_BEFORE[${i}]}
    INPUTFILES+=( "`echo ${FILE} | sed -e 's/ /#_#/g'`" ) #replace ' ' with '#_#'
done

入力ファイルを前処理して、スペースが含まれるファイル名に「#_#」を追加します...最後に、「完全な」スクリプト:

...

INPUTFILES_BEFORE=("data1.txt" "data2 with spaces.txt" "data3.txt")
INPUTFILES=()
for (( i=0; i < ${#INPUTFILES_BEFORE[@]}; i++)); do 
    FILE=${INPUTFILES_BEFORE[${i}]}
    INPUTFILES+=( "`echo ${FILE} | sed -e 's/ /#_#/g'`" ) #replace ' ' with '#_#'
done

for LINE in $( seq 0 $(( MAXROWS - 1 )) );do
gnuplot <<EOF
filenames="${INPUTFILES[@]}"
replace(S,C,R)=(strstrt(S,C)) ? \
        replace( S[:strstrt(S,C)-1].R.S[strstrt(S,C)+strlen(C):] , C ,R) : S
#replace '#_#' with ' ' in filenames.
plot for [file in filenames] replace(file,'#_#',' ') every ::0::${LINE} using 1:2 with line title "graf_${LINE}"

EOF
done

ただし、ここでのポイントは、ファイル名にスペースを使用しないことです ;)

于 2012-06-19T23:48:54.737 に答える
0

スペースをエスケープします。

"data2\ with\ spaces.txt"

編集

あなたが言及したように、エスケープシーケンスを使用しても、bashforは常にスペースの入力を解析するようです。

whileループ方式で動作するようにスクリプトを変換できますか:

http://ubuntuforums.org/showthread.php?t=83424

これも解決策かもしれませんが、私にとっては新しいものであり、それが何をしているのかを正確に理解するためにまだ遊んでいます:

http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html

于 2012-06-19T21:05:27.483 に答える