linux: sed match 小技巧 / 疑難雜症



前言

  • 用到 sed 指令在做字串操作時,不時會有一些出乎意料的小困難,記在這邊。



小技巧

取代字串

搜尋與顯示的語法,大概像這樣:

1
2
3
4
sed 's/<搜尋 pattern>/<顯示項目>/'

# 大部分做法
echo "<INPUT_TEXT>" | sed 's/<搜尋 pattern>/<顯示項目>/'

有的時候輸入的字串較長,只想去蕪存菁、留下符合 <pattern> 項目的時候,要在頭尾補上 .*

長得像是:

1
sed 's/.*<搜尋 pattern>.*/<顯示項目>/'

舉例來說

一段字串 INPUT_TEXT="In computer programming, a string is traditionally a sequence of characters, either as a literal constant or as some kind of variable. "

如果想把其中的 sequence of characters 改成 ktlast

1
2
3
4
5
6
7
echo "${INPUT_TEXT}";
echo "${INPUT_TEXT}" | sed 's/sequence of characters/ktlast/'

# result
In computer programming, a string is traditionally a sequence of characters, either as a literal constant or as some kind of variable.

In computer programming, a string is traditionally a ktlast, either as a literal constant or as some kind of variable.

只顯示符合 pattern 的字串

作法跟上面取代字串邏輯類似,但是這次是把「取代的範圍」改成「全部字串」:

1
echo "<INPUT_TEXT>" | sed 's/.*\(<搜尋 pattern>\).*/\1/'

這邊會需要 regex 的 group 概念基礎會比較好理解。

.*\(<搜尋 pattern>\).*:代表「全部的字串」、然後把符合 pattern 的項目存在 group 1;所以後面可以用 **\1** 取回來。

整句指令就代表:「把所有的字串用符合的 pattern 取代」。

所以如果只有打 sed 's/\(<搜尋 pattern>\)/\1/' 是不會生效的,因為這樣「取代的範圍」只有「符合 pattern 的範圍」而已。


Note

  1. 一般 regex 分組只要用括號 () 就好,為什麼這邊要跳脫?
    因為 sed 預設是用 Basic Regular Expressions (BRE),分組的寫法就是要包含跳脫:\(\)
    而不用跳脫的是 Extended Regular Expressions (ERE),這也是多數高階語言用的版本。



REF

Licensed under CC BY-NC-SA 4.0
最後更新 2024-05-24 14:47

主題 StackJimmy 設計