字串操作(Manipulating Strings)

在 Octave 中有很多可以處理字串操作的函數,由於字串本身就是以矩陣的方式儲存,因此可以使用一般的運算子進行簡單的字串操作,下面的範例說明如何將字串中的空白字元替換成下底線:

quote = "First things first, but not necessarily in that order";
quote( quote == " " ) = "_"

輸出為

quote = First_things_first,_but_not_necessarily_in_that_order

對於較複雜的字串操作,例如搜尋、取代與常規表示法可以使用下面的函數:

deblank (s)

deblank(s) 函數會移除字串 s 結尾處的空白與 null 字元,若 s 為字元陣列,則會將每一列(row)結尾的共同空白移除,若 s 為字串的巢狀陣列,則 deblank() 函數會以遞迴的方式,將巢狀陣列中的每一個字串結尾處的空白都移除。例如:

s = "string  ";
s2 = deblank(s);
whos s s2

輸出為

  Attr Name        Size                     Bytes  Class
  ==== ====        ====                     =====  ===== 
       s           1x8                          8  char
       s2          1x6                          6  char

字元陣列的範例:

m = ["ab     "; "12345  "; "xyz    "];
m2 = deblank(m);
whos m m2

輸出為

  Attr Name        Size                     Bytes  Class
  ==== ====        ====                     =====  ===== 
       m           3x7                         21  char
       m2          3x5                         15  char

字元矩陣 m 是一個 37 的矩陣,三個列的結尾都有共同的兩個空白字元,因此 deblank() 函數會移除每一列的最後兩個空白,最後得到的 m235 的字元矩陣。

巢狀陣列的範例:

a = {"ABC  ", "12 "};
b = deblank(a);
whos a{1} a{2} b{1} b{2}

輸出為

  Attr Name        Size                     Bytes  Class
  ==== ====        ====                     =====  ===== 
       a{1}        1x5                          5  char
       a{2}        1x3                          3  char
       b{1}        1x3                          3  char
       b{2}        1x2                          2  char
strtrim (s)

strtrim(s) 函數會移除字串 s 開頭與結尾處的空白與 null 字元,若 s 為字元矩陣,則會將每一列(row)開頭與結尾處的共同空白移除,若 s 為字串的巢狀陣列,則 strtrim() 函數會以遞迴的方式,將巢狀陣列中的每一個字串開頭與結尾處的空白都移除。例如:

strtrim ("    abc  ")

輸出為

ans = abc
strtrim ([" abc   "; "   def   "])

輸出為

ans =

abc  
  def
strtrunc (s, n)

strtrunc(s, n) 函數會擷取字串 s 的開頭前 n 個字元,若 s 為字元矩陣,則擷取開頭的前 n 個行(column);若 s 為字串的巢狀陣列,則 strtrunc() 函數會擷取巢狀陣列中每一個自串的開頭前 n 個字元,並傳回新的巢狀陣列。

findstr (s, t, overlap)

findstr(s, t) 函數可搜尋 st 兩個字串之中較短的字串在較長字串中出現的位置,例如:

findstr ("ababab", "a")

輸出為

ans =

   1   3   5

也可以寫成這樣

findstr ("a", "ababab")

輸出為

ans =

   1   3   5

若將 overlap 參數設為 0,則輸出的位置就不會重複:

findstr ("abababa", "aba", 0)

輸出為

ans =

   1   5

若不設定 overlap 參數,則預設會輸出重複的位置,例如:

findstr ("abababa", "aba")

輸出為

ans =

   1   3   5
idx = strchr (str, chrs)
idx = strchr (str, chrs, n)
idx = strchr (str, chrs, n, direction)

strchr() 函數與 find() 函數類似,strchr(str, chars) 函數會搜尋字串 chars 中所指定的字元出現在字串 str 中的位置,例如:

strchr("abcd1234abcd", "b3")

輸出為

ans =

    2    7   10

這會傳回字串 "abcd1234abcd" 中所有出現字元 "b""3" 的位置。

參數 n 是限制最多搜尋的個數,參數 direction 是尋找的方向,可以設定為 "first" (從開頭開始向後搜尋)或 "last"(從結尾開始像前搜尋),例如:

strchr("abcd1234abcd", "b3", 2, "last")

輸出為

ans =

    7   10
strchr() 函數的搜尋速度在大部分的情況會比常規表示法函數快。
index (s, t)
index (s, t, direction)

index(s, t) 函數會傳回字串 s 中第一個出現字串 t 的位置,若字串 s 中沒有出現字串 t 則傳回 0,例如:

index ("Teststring", "t")

輸出為

ans =  4

參數 direction 是指定搜尋方向,若指定為 "first" 則傳回第一個出現的位置,若指定為 "last" 則傳回最後一個出現的位置。

index() 函數不適用於字串陣列或是字元矩陣。
rindex (s, t)

rindex(s, t) 函數會傳回字串 s 中最後一個出現字串 t 的位置,若字串 s 中沒有出現字串 t 則傳回 0,此函數之功用等同於 index()direction 參數設為 "last"。例如:

rindex ("Teststring", "t")

輸出為

ans =  6
rindex() 函數不適用於字串陣列或是字元矩陣。
strfind (str, pattern)
strfind (cellstr, pattern, direction)

strfind(str, pattern) 函數會搜尋 pattern 在字串 str 中出現的位置,若沒有出現或 pattern 的長度比 str 的長度長,則傳回空陣列 []。若 str 指定為字串的巢狀陣列,則傳回值為向量的巢狀陣列。例如:

strfind ("abababa", "aba")

輸出為

ans =

   1   3   5
strfind ({"abababa", "bebebe", "ab"}, "aba")

輸出為

ans =

{
  [1,1] =

     1   3   5

  [1,2] = [](1x0)
  [1,3] = [](1x0)
}
strmatch (s, a, "exact")

strmatch(s, a) 函數傳回在 a 中出現字串 s 的元素索引,其傳回值是一個行向量,參數 a 為字元矩陣或字串的巢狀陣列。若沒有設定 "exact" 參數,則只比對開頭是否與 s 相同。null 字元會比對空白字元。例如:

strmatch ("apple", "apple juice")

輸出為

ans =  1
strmatch ("apple", ["apple pie"; "apple juice"; "an apple"])

輸出為

ans =

   1
   2
strmatch ("apple", {"apple pie"; "apple juice"; "tomato"})

輸出為

ans =

   1
   2
[tok, rem] = strtok (str, delim)

strtok(str, delim) 函數會找出 delim 之中的字元在字串 str 中第一個出現的位置,並將此字元之前的字串傳回(不包含此字元),若是有設定輸出參數 rem,則 rem 中會包含此字元之後的字串(包含此字元)。若是字串的第一個字元就在 delim 之中,則第一個字元會被忽略。若不指定 delim 則預設為空白字元。例如:

strtok ("this is the life")

輸出為

ans = this
[tok, rem] = strtok ("14*27+31", "+-*/")

輸出為

tok = 14
rem = *27+31
[s] = strsplit (p, sep, strip_empty)

strsplit(p, sep, strip_empty) 函數會以 sep 中的字元做為分隔字元,將字串 p 切成字串的巢狀陣列,字串 p 中若包含連續或位於字串兩端的分隔字元會使結果中產生空字串,若要將空字串移除,可指定 strip_empty 參數為 true,若不指定預設為 false。例如:

strsplit("this is the life", " ")

輸出為

ans =

{
  [1,1] = this
  [1,2] = is
  [1,3] = the
  [1,4] = life
}
strrep (s, x, y)

strrep(s, x, y) 函數會將字串 s 中所有出現字串 x 的地方都替換成字串 y,並傳回替換後的結過,例如:

strrep ("This is a test string", "is", "&%$")

輸出為

ans = Th&%$ &%$ a test string
substr (s, offset, len)

substr(s, offset, len) 函數傳回 s 字串的子字串,此子字串從 s 字串的第 offset 字元開始往後算起,長度為 len。若 offset 指定為負數,則開始的位置變成從 s 字串的結尾往前算。若不指定 len 參數,則傳回的子字串會取至 s 字串的結尾。例如:

substr ("This is a test string", 6, 9)

輸出為

ans = is a test
[s, e, te, m, t, nm] = regexp (str, pat)
[...] = regexp (str, pat, opts, ...)

regexp() 函數使用常規表示法(regular expression)進行字串的比對,在字串 str 中比對由 pat 所指定的常規表示法,並傳回符合的字串及其位置,若是找不到符合的字串則傳回空向量,pat 中可以使用任何標準的常規表示法,包含:

  • .:比對任意字元。
  • * + ? {} 重複運算子(Repetition operators):
    • *:比對 0 次以上。
    • +:比對 1 次以上。
    • ?:比對 0 次或 1 次。
    • {}:指定比對的次數,{n} 為剛好比對 n 次,{m,} 為比對 m 次以上,{m,n} 為比對 m 次到 n 次。
  • [...] [^...]:列舉運算子(List operators),例如 [ab]c 為比對 acbc
  • ():群組運算子(Grouping operator)。
  • |:多重選擇運算子(Alternation operator),比對其中一種常規表示法,此運算子必須配合上述的群組運算子使用。
  • ^ $:定位運算子(Anchoring operator),^ 比對字串 str 的開頭,$ 比對字串 str 的結尾。

下列的跳脫字元(escaped character)表示各種特殊意義,在使用這些跳脫字元時,建議使用單引號將常規表示法 pat 包起來,而不要使用雙引號,這樣可以避免這些跳說字元在傳給 regexp() 函數時就被 Octave 解析成其他的字元。

  • \b:比對字(word)的邊界。
  • \B:比對除了字邊界以外的地方。
  • \w:比對英文字字元。
  • \W:比對 \w 以外的字元。
  • \<:比對字(word)的開頭。
  • \>:比對字(word)的結尾。
  • \s:比對空白、Tab 等字元。
  • \S:比對 \s 以外的字元。
  • \d:比對數字。
  • \D:比對 \d 以外的字元。

regexp() 函數的傳回值預設是依照下面的順序傳回:

  • s:每一個符合的子字串起始索引值。
  • e:每一個符合的子字串結尾索引值。
  • te:包含所有在 pat 中被群組運算子 () 包起來的區段索引。
  • m:一個巢狀陣列,包含所有比對符合的內容。
  • t:一個巢狀陣列,包含所有在 pat 中被群組運算子 () 包起來的區段內容。
  • nm:一個資料結構(structure),包含所有被具名的群組運算子 () 包起來的區段內容,一個名稱為 name 的群組運算子為 (?...)

regexp() 函數的傳回值格式可以藉由 opts 參數設定,可以指定傳回值與傳回的順序,可以用的選項有:

  • 'start':指定 s
  • 'end':指定 e
  • 'tokenExtents':指定 te
  • 'match':指定 m
  • 'token':指定 t
  • 'names':指定 nm

regexp() 函數還有一些額外的參數:

  • 'once':只傳回第一個比對成功的結果。
  • 'matchcase':將英文大小寫視為不同。
  • 'ignorecase':將英文大小寫視為相同。
  • 'stringanchors':設定定位運算子比對整個字串的開頭與結尾。
  • 'lineanchors':設定定位運算子比對行(line)的開頭與結尾。
  • 'dotall':設定句點 . 可比對任意字元,包含換行字元。
  • 'dotexceptnewline':設定句點 . 可比對除了換行字元之外的任意字元。
  • 'freespacing':將 pat# 符號之後的所有內容或空白視為註解。
  • 'literalspacing':將在 pat 中的所有 # 符號視為一般字元來比對。
[s, e, te, m, t, nm] = regexpi (str, pat)
[...] = regexpi (str, pat, opts, ...)

regexpi() 函數與 regexp() 函數類似,但此函數將英文大小寫視為相同。

string = regexprep (str, pattern, repstr, options)

regexprep(str, pattern, repstr, options) 函數會以常規表示法 pattern 比對字串 str,並將比對符合的部分以 repstr 取代。repstr 中亦可以使用 $i 表示在 pattern 中第 i 個以括弧包起來的部分,例如:

regexprep("Bill Dunn", '(\w+) (\w+)', '$2, $1')

輸出為

ans = Dunn, Bill

參數 options 部分可以使用的有:

  • 'once':只替換第一個比對成功的結果。
  • 'warnings':這個參數是為了相容性而設置的,並沒有作用。
  • 'ignorecase''matchcase':設定是否將英文大小寫視為相同,亦可在 pattern 中以 (?i)(?-i) 指定。
  • 'lineanchors''stringanchors':設定定位運算子比對行(line)的開頭與結尾,或是比對整個字串的開頭與結尾,亦可在 pattern 中以 (?m)(?-m) 指定。
  • 'dotexceptnewline''dotall':設定句點 . 是否比對換行字元,亦可在 pattern 中以 (?s)(?-s) 指定。
  • 'freespacing''literalspacing':設定 # 與空白是否可用於 pattern 中做為註解,亦可在 pattern 中以 (?x)(?-x) 指定。

例如:

regexprep("ABC\nabc\nAbc", "^ab", "XY", 'ignorecase', 'lineanchors')

輸出為

ans = XYC
XYc
XYc
regexptranslate (op, s)

regexptranslate(op, s) 函數會將字串 s 轉換為常規表示法中使用的格式,參數 op 是指定轉換的類型,可用的選項有:

  • "wildcard":將 wildcard 字元轉換為常規表示法,例如 *? 等。
  • "escape":將跳脫字元轉換為常規表示法,例如 $ . ? [] 等。

下面是一些範例:

regexptranslate ("wildcard", "*.m")

輸出為

ans = .*\.m
regexptranslate ("escape", "12.5")

輸出為

ans = 12\.5