Sed

如何從 /begin/ 到 /end/ 讀取文件,如果兩者可能在同一行

  • December 30, 2020

我想通過一個大項目的原始碼來閱讀一個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)手冊頁。

引用自:https://unix.stackexchange.com/questions/626623