首頁>Linux>source

我想通過一个大專案的源代碼阅讀C函式的原型。

我知道函式名稱及其返迴型別,並且其原型將在 *.h中定義 檔案。

我会使用 grep(1) ,但我希望能够讀取多行原型,因此將其丢棄。

所以我通常要做的是:

  • project: glibc
  • 返迴型別: int
  • 函式名稱: cacheflush
syscall='cacheflush';
find glibc/ -name '*.h' \
|xargs sed -n "/^[a-z ]*int ${syscall}[ ]*(/,/^$/p";

但這会在我想要的行之後print一些不需要的行:

$ 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;
最新回復
  • 6月前
    1 #

    您可以使用 pcregrep 的多行模式:

    $ 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 .的標志 還要匹配換行符。

      *?*的非贪婪版本 .因此,它与 ;first匹配 而不是像贪婪的版本那樣。

      pcrepattern(3) 手册頁以获取详细資訊。

  • 6月前
    2 #

    無需呼叫 sed 两次,您只需在輸入範圍之前檢查開始/結束是否碰巧在同一行。

    $ find glibc/ -name '*.h' \
    |xargs sed \
        -e "/${pattern}.*;\$/b"  \
        -e "/${pattern}/,/;\$/p" \
        -e 'd' ;
    

    請註意,如果您限製 find 實用程式仅用於查詢常規檔案,否則在 sed時可能会看到警告 對名稱以 .h結尾的目錄进行操作

  • 6月前
    3 #

    我想出了一个(丑陋的)解決方案:

    /begin/阅讀 到 /^$/ (空白行),重複圖案的第一行,這樣 sed(1) 可以在後續步骤中對其采取行動。

    使用 sed(1)/begin/找到 到 /end/ .在此步骤中保留空白行即可使用 uniq(1) 以便在下一步中正確删除我们在步骤1中重複的行。

    使用 uniq(1) 删除重複的行。

    $ syscall=cacheflush;
    $ return=int;
    $ pattern="^[a-z ]*${return} ${syscall}[ ]*(";
    $ find glibc/ -name '*.h' \
      |xargs sed -n -e "/${pattern}/p" -e "/${pattern}/,/^$/p" \
      |sed -n -e "/${pattern}/,/;/p" -e '/^$/p' \
      |uniq;
    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;
    
    

    請,提供一个更簡單的解決方案:)

  • bash:而讀取迴圈在別名內部不起作用
  • linux:在啟動時分配大頁面的好處