string substitution
buf-insert 關(guān)鍵就是里面的擴(kuò)展的setf 方法。
buf-next只有在輸入的時(shí)候是從buffer里面來(lái)的時(shí)候才用buf-next。它是先比較當(dāng)前位置used是否小于buf-new,如果是就把下面那個(gè)輸出來(lái)。所以說(shuō)第二b仍舊會(huì)讀出來(lái)進(jìn)行匹配測(cè)試,當(dāng)它執(zhí)行完以后,然后再call buf-next的話,發(fā)現(xiàn)used跟new已經(jīng)相等了,所以只能是read里面讀取數(shù)據(jù)了。
buf-pop ? ?它是從棧出來(lái),只有執(zhí)行了princ才會(huì)輸出到out里面。所以說(shuō)你看zerop pos首先是princ,然后才是出棧。
buf-flush ?是為了解決一種情況:假設(shè)pattern為baro,現(xiàn)在文本中最后幾個(gè)字符為bar。因?yàn)檎麄€(gè)循環(huán)是到文件尾結(jié)束,現(xiàn)在bar還在buffer里面就結(jié)束了,所以將會(huì)顯示不出來(lái)。其他情況的話buf-flush要不要沒(méi)影響。
(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的長(zhǎng)度跟pattern串長(zhǎng)度一樣,(from-buf nil))(do ((c (read-char in nil :eof) ;初始時(shí)讀取一個(gè)字符(or (setf from-buf (buf-next buf)) ;因?yàn)橛卸搪番F(xiàn)象,要么從buffer中讀取,要不從流中。(read-char in nil :eof))))((eql c :eof)) ;循環(huán)結(jié)束條件是碰到了結(jié)尾(cond ((char= c (char old pos)) ;如果讀入的字符等于old中的一個(gè)字符(incf pos) ;pos+1,因?yàn)榉彩瞧ヅ涑晒Φ脑?#xff0c;pattern中的指標(biāo)就要加+指到下一位;;內(nèi)部cond判斷兩次(cond ((= pos len) ; 3 因?yàn)樯厦鎝os已經(jīng)加1了,所以說(shuō)只需相等就行了。(princ new out) ;把它輸出來(lái)(setf pos 0) ;pos 變?yōu)?(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 : 當(dāng)我們pop一個(gè)元素,他就會(huì)增加,增加buf-stard。end ? :當(dāng)我們插入一個(gè)元素的時(shí)候他會(huì)增加,先增加buf-end,然后再往這個(gè)buf-end里面添加值。
used ?: 當(dāng)我們pop完一個(gè)元素,然后就會(huì)調(diào)用bufnext,他會(huì)在里面累加。
new ? : 當(dāng)試著匹配buffer里面的字符時(shí),開始調(diào)用used/new,一旦buffer中匹配開始,new就會(huì)綁定到end,因?yàn)閑nd就相當(dāng)于是buffer里面最后一個(gè)元素,然后調(diào)用buf-next,進(jìn)行迭代匹配,直到used=new。也就是說(shuō)一旦檢測(cè)buffer的話,會(huì)把buffer里面所有的都試著匹配一遍,然后才會(huì)開始接受從read中讀取。
1:ring buffer空間只要跟pattern一樣就行。
2:短路現(xiàn)象中,在b-a-r的過(guò)程中因?yàn)殡m然這個(gè)時(shí)候buf-used< buf-new當(dāng)時(shí)取到的值為nil,所以仍舊是從流中讀取
from-buf意思就是從buf里面讀取數(shù)據(jù)成功。
3:什么時(shí)候第一次給used/new賦值的呢?也就是在第一次pop的時(shí)候進(jìn)行reset的時(shí)候才會(huì)給used/new進(jìn)行賦值。就像圖5,因?yàn)榍懊娴臅r(shí)候used/new都是-1,所以也都是按流讀入的。
Case1:zerop pos 首先表示的是一個(gè)新的匹配,并且前面沒(méi)有字符匹配成功的話,就把他輸出來(lái)。如u/s直接輸出來(lái)了。都沒(méi)有到buffer里面還有一種情況就是這個(gè)字符已經(jīng)在buffer里面了,但是前面沒(méi)有字符匹配成功,他就需要從buffer中出來(lái),并且重新設(shè)置pos為0(指向pattern的第一個(gè)位置)
Case2:當(dāng)匹配開始,也就是說(shuō)前面有字符匹配已經(jīng)匹配上了。當(dāng)讀入的字符不是來(lái)自于buffer(from-buf 為假),就將字符輸入到buffer里面。pos 指定到old string上面。當(dāng)字符與在pattern string的pos +1值一樣時(shí),說(shuō)明整個(gè)串匹配成功。
Case3:pos + 1 跟new string的長(zhǎng)度一樣,并且匹配在這個(gè)位置的元素匹配成功,就輸出一個(gè)新的string。重新把pattern匹配的起始位置設(shè)置為0,因?yàn)槟阋呀?jīng)匹配成功了,下一個(gè)再進(jìn)行匹配的話,只能是從頭開始。把buffer里面的東西請(qǐng)空。 ?因?yàn)橄忍幚硗阞uffer里面的東西,才會(huì)繼續(xù)從讀入新的值。比如當(dāng)你匹配a彈出的時(shí)候,他會(huì)再(setf from-buf (buf-next buf))
Case4:匹配到中途在這個(gè)位置不匹配了。pop第一個(gè)字符出棧,然后reset,并且設(shè)置pos從pattern頭開始重新匹配。因?yàn)槟爿斎氲臅r(shí)候就是兩種情況輸入的,一個(gè)是讀進(jìn)去,一個(gè)是from-buf.所以在你處理的時(shí)候也同樣是兩種情況處理。
首先按照匹配是否成功,然后再按照是否來(lái)自于文件輸入或者是buffer部分讀取。
總結(jié)
以上是生活随笔為你收集整理的string substitution的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Linux】Linux根目录下各个目录
- 下一篇: 为什么很多的企业留不住人才呢?