地球科學繪圖是由胡老師開的一門課,主要介紹使用通用製圖工具–Generic Mapping Tool 進行地球科學相關資料的繪圖工作。本文是記錄在修課時,由於本身使用 Mac 環境工作,然而範例都是以 Windows 的 Batch 環境為主,故寫了一個小小的 Python 程式來做轉換。
所需程式:基本上 Linux 系統都有內建 Python 2,應該不用額外安裝
- Python:2.6 以上,在 2.7.10 執行無誤,3以上版本未測試(print未更改)
使用說明:
在命令列中:
$python DosToBash.py input_filename [arguments]
其中 [arguments] 為以下選項,用於控制執行的模式:
arguments:
input_filename : Required. 輸入的檔案,必須給的參數且需放在第二個變數
-p : print out all the lines for inputfile. 純粹列出文字檔所有的內容。
–help : print help information. 印出使用說明。
–out=filename : specify the output filename. 指定輸出檔案的檔名,預設為filename.sh。
–edit=True : edit variables. 編輯文章內的變數。輸入後當掃描到 SET var1=original 時,會等待使用者輸入新的 var1 變數值。
更新紀錄:隨著課程遇到越來越多不同的指令,慢慢加入新的並且更加精確的修正。
v0323:
add tempfile module.
change “\r\n” to “\n”
“gawk” to “awk”, “” to ”
v0329:
change “rem” to “#”
v0402:
major update
new class: key_word_process:
__init__ : initialization
_add_var : add variable to the dictionary ‘var’, even edit it.
_get_var_value_line : return a line with variable setting.
_bat_to_sh_var : replace all variables stored in ‘var’ in the given sentence
pip_line_process : divide the pipe command in to two sentence and process with ‘parser’
parser : the parser, the return the replaced sentence.
now the scipt is able to process pipe(|) commands
add arguments :
-p : print out all the lines for inputfile
–help : print help information
–out=filename : specify the output filename
–edit=True : edit variables
add function :
main_process : construct ‘key_word_process’, call functions in ‘key_word_process’ and write file.
print_all_line : print all the line in the file include hidden characters
print_help : print help informations
v0405:
new keyword “Set”, equal to “set” (06a)
v0406:
solve the problem – the parser will not parse the second command of pipe(|) because of the space.
(Use lstrip to fix it)
程式做的事:
- 修改換行符號 \r\n 為 \n 。
- 辨認 SET var=* 的命令,轉為 var=* 或是使用者指定的新變數。
- 消除 pause 指令( bash 無)。
- 註解 REM 轉為#。
- 刪除檔案 DEL 轉為 rm。
- 列舉或是印出文字文件的 type 命令改為 cat。
- gawk 改為 awk ,且雙引號 ” 改為 單引號 ‘ 。
程式碼:(未來有時間再解釋相關內容,不過註解寫滿多的應該不難讀 :P)
''' Script Name : DosToBash.py * Minimum python version : 2.6 ( str.format() ) * Test python version : 2.7.10 64-bit on MacOSX 10.11 Purpose : change DOS commands to bash command so that mac can run course example Authur : CWSun @ NTU 2016.04 Mail : [email protected] Description: This tool will find the specified words in "key_word_process.var" and replace them . Then we will check some special syntax like "%filename%" to "$filename" . ========== How to use : in command line, type: $python DosToBash.py input_filename [arguments] arguments: input_filename : Required. -p : print out all the lines for inputfile --help : print help information --out=filename : specify the output filename --edit=True : edit variables ''' import io,os,sys,tempfile code_version = "g20160406-1735" class key_word_process(): def __init__(self,edit=False): self.var={} self.edit_var=edit def _add_var(self,set_line): ''' Input : (String)the line begin with "set var=value" Add key and value in to the dictionary "self.var" ''' tmp_list=set_line.split(" ")[1].split("=") if self.edit_var==True: print "\nVariable \'{0}\' detected, the default value is\n{1}".format(tmp_list[0],tmp_list[1].rstrip('\n')) newvalue=raw_input("Type new value here:") if newvalue != '': self.var[ tmp_list[0] ]=(newvalue+'\n') else: self.var[ tmp_list[0] ]=self._bat_to_sh_var(tmp_list[1]) else: self.var[ tmp_list[0] ]=self._bat_to_sh_var(tmp_list[1]) def _get_var_value_line(self,key): ''' Use this function to get the key-value sentence Input : var_name (key) Output : a string in sentence (eg. "key=value\n") ''' if not self.var.has_key(key): print "[Error] No variable named \"{0}\"".format(key) return (key+"\n") return str(key+"="+self.var[key]) def _bat_to_sh_var(self,string): ''' Input:the string list. eg. "string".split(" ") change %var% to $var ''' for key in self.var.iterkeys(): string = string.replace(str("%"+key+"%"),str("$"+key)) #string = string.replace(str("%"+key+"%\n"),str("$"+key+"\n")) return string #string def pip_line_process(self,line): line_list = line.split("|") new=[] for i in range(len(line_list) ): if i == 0: new.append(self.parser(line_list[i])) else: new.append(" "+self.parser(line_list[i].lstrip(" "))) return ( "|".join(new) ) def parser(self,line): tmp_line_list=line.split(" ") #Start to process the alteration #[first only] set --> add variable to var(dictionary) if tmp_line_list[0] in ["set","Set","SET"]: self._add_var(line) return self._get_var_value_line(tmp_line_list[1].split("=")[0]) #[first only] pause --> "" elif tmp_line_list[0] in ["pause\n","PAUSE\n"]: return "" #[first only] REM --> # elif tmp_line_list[0] in ["REM","rem","Rem"]: tmp_line_list[0] = "#" return self._bat_to_sh_var(" ".join(tmp_line_list) ) elif tmp_line_list[0] in ["REM\n","rem\n","Rem"]: return "#\n" #[first only] del --> rm elif tmp_line_list[0] in ["del","DEL","Del"]: tmp_line_list[0]="rm" return (" ".join(tmp_line_list)) #[first only] type --> cat elif tmp_line_list[0] in ["type","TYPE","Type"]: tmp_line_list[0]="cat" return (" ".join(tmp_line_list)) #[first only] gawk --> awk ; "" -> '' elif tmp_line_list[0]=="gawk": tmp_line_list = line.split("\"") tmp_line_list[0]=tmp_line_list[0].replace("gawk","awk") return self._bat_to_sh_var( ("\'".join(tmp_line_list)) ) else: #eg. gmt command return self._bat_to_sh_var(line) def main_process(infile,outfile,edit_var=False): ''' Please open the file before calling this function !! ''' go=key_word_process(edit=edit_var) outfile.write("# This file is automatically generated by DosToBash.py\n") for line in infile: sys.stdout.write('*') #Just for counting lines and show on the screen if line.find("|") != -1: # Use the pipe command in the line command outfile.write(go.pip_line_process(line) ) else: # No pipe command in command (no "|") outfile.write(go.parser(line) ) def remove_r(InPath,tmpfile): with io.open(InPath,'rb') as infile: for line in infile: tmpfile.write(line.rstrip("\r\n")+'\n') def print_all_line(InputFilePath): print "{:=^30}".format("Begin of the file") with io.open(InputFilePath,"rb") as InputFile: for line in InputFile: print repr(line) print "{:=^30}".format("End of the file") def print_help(mode=1): if mode == 0 : #help print "Use python DosToBash.py --help \nto get help" print "The script will exit now." elif mode == 1 : #syntax error print "\nHow to use :\npython DosToBash.py input_filename [arguments]" print "\n{0}".format("arguments:\n-p : print out all the lines for inputfile\n--help : print help information\n--out=filename : specify the output filename\n--edit=True : edit variables") if __name__ == "__main__": edit_mode = False print "\n{:=^30}".format("==") print "Script Name : DosToBash.py" print "Purpose : change BATCH commands to BASH command so that Linux/Mac can run GMT2016 course example." print "Authur : CWSun @ NTU v{0}".format(code_version) ''' arguments: input_filename : Required. -p : print out all the lines for inputfile --help : print help information --out=filename : specify the output filename --edit=True : edit variables ''' if len(sys.argv) == 1: print_help(1) tmp = raw_input("\nPress return to exit...\n") sys.exit(0) if not os.path.exists(sys.argv[1]): #File does not exist print "[Error] parameter 1 ({0}) is not a file.".format(sys.argv[1]) sys.exit(0) AbspthOfFile=os.path.abspath(sys.argv[1]) outputfilename=(os.path.splitext(AbspthOfFile)[0]+".sh") paras=sys.argv[2:] for p in paras: if p =="-p": print_all_line(AbspthOfFile) tmp = raw_input("\nPress return to exit...\n") sys.exit(0) elif p == "--help": print_help(1) tmp = raw_input("\nPress return to exit...\n") sys.exit(0) elif p.startswith("--out"): outputfilename=(os.path.join(os.path.dirname(AbspthOfFile),p.split("=")[1])) elif p.startswith("--edit"): if p.split("=")[1].title() == "True": edit_mode = True elif p.split("=")[1].title() == "False": edit_mode = False else: print "[Error] you should use True/False in parameter \"--edit\"" sys.exit(0) else: print "[Error] invalid argument {0}".format(p) print_help(0) sys.exit(0) print "\n{:=^30}".format("Creating tempfile") tempf = tempfile.TemporaryFile() print "\n{:=^30}".format("Removing \\r\\n") # Remove "\r\n" to avoid error in bash remove_r(AbspthOfFile,tempf) # Set the cursor to the head of the file tempf.seek(0) #begin main process print "\n{:=^30}".format("Begining main process") with io.open(outputfilename,"wb") as out_file: main_process(tempf,out_file,edit_mode) print "\n{:=^30}".format("Closing tempfile") tempf.close() print "\n{:=^30}".format(" Done ") print "processed file : " print "\n{0:<30}".format(outputfilename) print "\n{0:<30}".format("Notice : You should change os-dependent filepath on your own. (like d:\\files\)\n") tmp = raw_input("Press \"return to exit\"\n") ''' Log : v0323: add tempfile module. change "\r\n" to "\n" "gawk" to "awk", "" to '' v0329: change "rem" to "#" v0402: major update new class:key_word_process: __init__ : initialization _add_var : add variable to the dictionary 'var', even edit it. _get_var_value_line : return a line with variable setting. _bat_to_sh_var : replace all variables stored in 'var' in the given sentence pip_line_process : divide the pipe command in to two sentence and process with 'parser' parser : the parser, the return the replaced sentence. now the scipt is able to process pipe(|) commands add arguments : -p : print out all the lines for inputfile --help : print help information --out=filename : specify the output filename --edit=True : edit variables add function : main_process : construct 'key_word_process', call functions in 'key_word_process' and write file. print_all_line : print all the line in the file include hidden characters print_help : print help informations v0405: new keyword "Set", equal to "set" (06a) v0406: solve the problem - the parser will not parse the second command of pipe(|) because of the space. (Use lstrip to fix it) '''