2012-06-19 42 views
4

我在bash中有一個小腳本,它通過gnuplot生成圖形。 一切正常,直到輸入文件的名稱包含空格。gnuplot循環和文件名空間

這裏就是我已經有了:

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 
+1

不要使用'seq'。對於((line = 0; line ormaaj

+0

@ormaaj修正了問題。我想到了一些來自gnuplot的系統調用..就像sed將空格切換爲破折號,然後再次返回。 爲什麼不使用seq(可讀性?!)和全大寫變量名? – Rob

回答

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 

但是,我認爲這裏的外延是你不應該在文件名中使用空格;)

+0

是的,就是這樣。我幾乎做了不可思議和實施的解決方案與tmp文件(原件的副本,但沒有空格的名稱):)謝謝! – Rob

+1

@Rob - 編輯好。這對我來說是一個非常有趣的小挑戰。謝謝 – mgilson

0

逃生的空間:

"data2\ with\ spaces.txt" 

編輯

看來,即使轉義序列,正如你所提到的, bash for將始終解析空間上的輸入。

你可以把你的腳本在while循環方式工作:

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

這也可能是一個解決方案,但它是新的給我,我仍然在擺弄它,瞭解到底是什麼它是這樣做的:

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

+0

這沒有幫助。正如你所看到的,我的INPUTFILES在「」 – Rob

+0

問題出現在gnuplot「循環」評估中。Gnuplot完全不關心「」。 – Rob

+0

我熟悉bash IFS變量,但是**這個問題是關於「** gnuplot ** for循環評估」的。 – Rob