Sed
如何從 /begin/ 到 /end/ 讀取文件,如果兩者可能在同一行
我想通過一個大項目的原始碼來閱讀一個C函式的原型。
我知道函式名和它的返回類型,並且它的原型將在一個
*.h
文件中定義。我會使用
grep(1)
,但我希望能夠讀取多行原型,所以它被丟棄了。所以我通常做的是:
- 項目:
glibc
- 返回類型:
int
- 函式名稱:
cacheflush
syscall='cacheflush'; find glibc/ -name '*.h' \ |xargs sed -n "/^[a-z ]*int ${syscall}[ ]*(/,/^$/p";
但這會在我想要的行之後列印一些不需要的行:
$ find glibc/ -name '*.h' \ |xargs sed -n "/^[a-z ]*int ${syscall}[ ]*(/,/^$/p"; extern int cacheflush (void *__addr, int __nbytes, int __op) __THROW; #endif extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; #endif extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; #endif extern int _flush_cache (char *__addr, const int __nbytes, const int __op) __THROW; extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; #endif extern int _flush_cache (char *__addr, const int __nbytes, const int __op) __THROW;
我希望能夠替換結束模式
/^$/
->/;/
,但是只有當函式原型跨越多行時它才會起作用。是否可以判斷sed(1)
結束模式可能與開始模式在同一行,以便輸出如下?:$ find glibc/ -name '*.h' | xargs sed magic; extern int cacheflush (void *__addr, int __nbytes, int __op) __THROW; extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW;
您可以使用
pcregrep
’s 多行模式:$ pcregrep --include='\.h$' -rM '(?s)^\s*(\w+\s+)*int cacheflush\s*\(.*?;' glibc glibc/sysdeps/unix/sysv/linux/mips/sys/cachectl.h:extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; glibc/sysdeps/unix/sysv/linux/csky/sys/cachectl.h:extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW; glibc/sysdeps/unix/sysv/linux/nios2/sys/cachectl.h:extern int cacheflush (void *__addr, const int __nbytes, const int __op) __THROW;
使用 PCRE,您可以訪問大多數 perl 的高級正則表達式運算符。在這裡,我們使用:
\w
,\s
對於單詞和空白字元。(?s)
: 使s
標誌 for.
也匹配換行符。*?
: 的非貪婪版本*
。所以它匹配第一次出現;
而不是像貪婪版本那樣的最後一次出現。有關詳細資訊,請參見
pcrepattern(3)
手冊頁。