2017-08-01 66 views
2

我寫了一個腳本來修飾我的.bash_history文件,從持久化歷史過濾「無趣」命令,如ls。我知道有HISTIGNORE變量,但這也會排除當前會話的內存歷史記錄中的這些命令,我​​發現將它們放在一個會話的範圍內是有用的,但不會在會話中持久化。 )這個過濾器可以使用Sed實現嗎?

歷史文件可以包含帶有嵌入換行符的多行歷史記錄條目,因此這些條目由時間戳分隔。該腳本需要像輸入文件:

#1501304269 
git stash 
#1501304270 
ls 
#1501304318 
ls | while IFS= read line; do 
echo 'line is: ' $line 
done 

並篩選出單行lsmancat命令,產生:

#1501304269 
git stash 
#1501304318 
ls | while IFS= read line; do 
echo 'line is: ' $line 
done 

注意,多行條目是未經過濾的 - 我的身影如果它們足夠有趣以保證多行,那麼它們值得記住。

我實現了它在awk中,但我一直在閱讀有關桑達的多能力(NhHx等),我想試試這個目的。如果沒有別的,我會好奇地比較兩個速度。

這裏的awk腳本:

/^#[[:digit:]]{10}$/ { 
    timestamp = $0 
    histentry = "" 
    next 
} 
$1 ~ /^(ls?|man|cat)$/ { 
    if (! timestamp) { 
    print 
    } else { 
    histentry = $0 
    } 
    next 
} 
timestamp { 
    print timestamp 
    timestamp = "" 
} 
histentry { 
    print histentry 
    histentry = "" 
} 
{ print } 

可以這樣使用桑達做?

+0

您是否瞭解'HISTIGNORE'? https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash - 你可以在你的.bashrc中導出HISTIGNORE = ls:man:cat',它會執行無需編寫任何代碼就可以實現類似的功 –

+1

@JohnZwinck是的,但是那些命令在我當前的會話中也會被忽略。我經常點擊'up'或'ctrl-p'來回憶最近的'ls'並調整它,所以我不想在這種情況下使用'HISTIGNORE'。 – ivan

+1

如果你是一個受虐狂,你可能可以用'sed'來實現。鑑於你在awk中有一個完美的版本,我會計算我的幸運星,並轉向其他追求;-)。除非您使用Pentium 3硬件,否則速度不會有任何顯着差異;-)。只是恕我直言。祝你們好運!。 – shellter

回答

1

當然可以用sed來完成。下面是使用GNU SEDS -z選項,它可以讓我們處理整個文件一次,而不是工作線的線路爲例:

sed -rz "s/(#[0-9]{10}\n(cat|ls|man)\n)+(#[0-9]{10}\n|$)/\3/g;" yourfile 

如果一切正常,你有你的歷史文件的備份,你甚至可能使用GNU sed -i選項進行就地修改。

-r選項啓用擴展的regexp,所述-z選項在說明書中介紹的是這樣的:

對待輸入作爲一組線,由一個零字節 (ASCII碼「NUL」各自終止字符)而不是換行符。這個選項可以用 與'sort -z'和'find -print0'這樣的命令來處理 任意文件名。

基本思想是這樣的:一個無趣的命令前後有一個時間戳(或者它是文件的最後一行)。

  • 時間戳RE #[0-9]{10}從您的awk腳本採取
  • (#[0-9]{10}\n(cat|ls|man)\n)+匹配的一個或多個的無趣命令
  • (#[0-9]{10}|$)第二時間戳被捕獲到\3(由於在第三對括號的是)用於替換零件和替換|$適合文件結尾
+0

哇,這實際上比我試過的一切簡單得多。我必須安裝gnu-sed,因爲我在Mac上,而BSD sed不支持'-z'。 – ivan