string substitution
buf-insert 關鍵就是里面的擴展的setf 方法。
buf-next只有在輸入的時候是從buffer里面來的時候才用buf-next。它是先比較當前位置used是否小于buf-new,如果是就把下面那個輸出來。所以說第二b仍舊會讀出來進行匹配測試,當它執行完以后,然后再call buf-next的話,發現used跟new已經相等了,所以只能是read里面讀取數據了。
buf-pop ? ?它是從棧出來,只有執行了princ才會輸出到out里面。所以說你看zerop pos首先是princ,然后才是出棧。
buf-flush ?是為了解決一種情況:假設pattern為baro,現在文本中最后幾個字符為bar。因為整個循環是到文件尾結束,現在bar還在buffer里面就結束了,所以將會顯示不出來。其他情況的話buf-flush要不要沒影響。
(defun file-subst (old new file1 file2)(with-open-file (in file1 :direction :input)(with-open-file (out file2 :direction :output:if-exists :supersede)(stream-subst old new in out))))(defun stream-subst (old new in out)(let* ((pos 0)(len (length old)) (buf (new-buf len)) ;buffer的長度跟pattern串長度一樣,(from-buf nil))(do ((c (read-char in nil :eof) ;初始時讀取一個字符(or (setf from-buf (buf-next buf)) ;因為有短路現象,要么從buffer中讀取,要不從流中。(read-char in nil :eof))))((eql c :eof)) ;循環結束條件是碰到了結尾(cond ((char= c (char old pos)) ;如果讀入的字符等于old中的一個字符(incf pos) ;pos+1,因為凡是匹配成功的話,pattern中的指標就要加+指到下一位;;內部cond判斷兩次(cond ((= pos len) ; 3 因為上面pos已經加1了,所以說只需相等就行了。(princ new out) ;把它輸出來(setf pos 0) ;pos 變為0(buf-clear buf)) ;buffer 清空((not from-buf) ; 2 (buf-insert c buf))))((zerop pos) ; 1(princ c out)(when from-buf(buf-pop buf)(buf-reset buf)))(t ; 4(unless from-buf(buf-insert c buf))(princ (buf-pop buf) out)(buf-reset buf)(setf pos 0))))(buf-flush buf out)))start : 當我們pop一個元素,他就會增加,增加buf-stard。end ? :當我們插入一個元素的時候他會增加,先增加buf-end,然后再往這個buf-end里面添加值。
used ?: 當我們pop完一個元素,然后就會調用bufnext,他會在里面累加。
new ? : 當試著匹配buffer里面的字符時,開始調用used/new,一旦buffer中匹配開始,new就會綁定到end,因為end就相當于是buffer里面最后一個元素,然后調用buf-next,進行迭代匹配,直到used=new。也就是說一旦檢測buffer的話,會把buffer里面所有的都試著匹配一遍,然后才會開始接受從read中讀取。
1:ring buffer空間只要跟pattern一樣就行。
2:短路現象中,在b-a-r的過程中因為雖然這個時候buf-used< buf-new當時取到的值為nil,所以仍舊是從流中讀取
from-buf意思就是從buf里面讀取數據成功。
3:什么時候第一次給used/new賦值的呢?也就是在第一次pop的時候進行reset的時候才會給used/new進行賦值。就像圖5,因為前面的時候used/new都是-1,所以也都是按流讀入的。
Case1:zerop pos 首先表示的是一個新的匹配,并且前面沒有字符匹配成功的話,就把他輸出來。如u/s直接輸出來了。都沒有到buffer里面還有一種情況就是這個字符已經在buffer里面了,但是前面沒有字符匹配成功,他就需要從buffer中出來,并且重新設置pos為0(指向pattern的第一個位置)
Case2:當匹配開始,也就是說前面有字符匹配已經匹配上了。當讀入的字符不是來自于buffer(from-buf 為假),就將字符輸入到buffer里面。pos 指定到old string上面。當字符與在pattern string的pos +1值一樣時,說明整個串匹配成功。
Case3:pos + 1 跟new string的長度一樣,并且匹配在這個位置的元素匹配成功,就輸出一個新的string。重新把pattern匹配的起始位置設置為0,因為你已經匹配成功了,下一個再進行匹配的話,只能是從頭開始。把buffer里面的東西請空。 ?因為先處理完buffer里面的東西,才會繼續從讀入新的值。比如當你匹配a彈出的時候,他會再(setf from-buf (buf-next buf))
Case4:匹配到中途在這個位置不匹配了。pop第一個字符出棧,然后reset,并且設置pos從pattern頭開始重新匹配。因為你輸入的時候就是兩種情況輸入的,一個是讀進去,一個是from-buf.所以在你處理的時候也同樣是兩種情況處理。
首先按照匹配是否成功,然后再按照是否來自于文件輸入或者是buffer部分讀取。
總結
以上是生活随笔為你收集整理的string substitution的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux】Linux根目录下各个目录
- 下一篇: python如何实现飞机上下移动_pyt