題 在linux上使用命令行作為bash別名時出錯


我想將以下命令行序列保存為bash別名:

grep  `date '+%d/%b/%Y'` access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '{print $1, $4, $5, $7, $8, $9, $10}' | sort |uniq -c -w15 |sort -n

它在命令行中運行良好,但在我嘗試將其設置為別名時失敗。我嘗試將以下內容添加到.bash_profile:

alias downloads="grep  `date '+%d/%b/%Y'` access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '{print $1, $4, $5, $7, $8, $9, $10}' | sort |uniq -c -w15 |sort -n"

我收到以下錯誤:

-bash-3.2$ downloads
awk: {print , , , , , , 0}
awk:        ^ syntax error
awk: {print , , , , , , 0}
awk:          ^ syntax error
awk: {print , , , , , , 0}
awk:            ^ syntax error
awk: {print , , , , , , 0}
awk:              ^ syntax error
awk: {print , , , , , , 0}
awk:                ^ syntax error
awk: {print , , , , , , 0}
awk:                  ^ syntax error

我究竟做錯了什麼????


4
2017-09-26 23:15


起源




答案:


坦率地說,當命令變得那麼大時,我會把它變成一個腳本而不是一個別名。腳本的一個優點是,您可以使用更多文件而不僅僅是“access.logs”。

該命令序列涉及單引號和反引號 - 這總是增加了樂趣。一般來說,你最好使用 $(command args) 代替後引號。

當您在別名周圍使用雙引號時,將在創建別名時執行反引號命令 - 除非shell在定義別名時使用不同的方式解釋事物。也, $var 表達式在雙引號內進行求值,所以你的 awk 錯誤表明您在當前shell中沒有參數。

因此,如果必須使用別名,那麼您可能需要在整個表達式周圍使用單引號,再加上表達式中出現的每個單引號,將其替換為序列quote-backslash-quote-quote: '\''。第一個引號終止當前引用的字符串;反斜杠引號代表字面引用;最終報價重新啟動引用的字符串。

這導致:

alias downloads='grep  `date '\''+%d/%b/%Y'\''` access.logs |
                 egrep 2765330645ae47d292c9ceac725d744e.py |
                 awk '\''{print $1, $4, $5, $7, $8, $9, $10}'\'' |
                 sort | uniq -c -w15 | sort -n'

5
2017-09-27 02:14



這是很好的建議!您也可以創建一個'bash函數',但實際上可能更喜歡腳本(至少對於變量作用域目的而言)。子函數不會繼承函數,但仍可以通過$ PATH找到腳本 - ericslaw
“功能不是由子殼繼承的” - 但你可以做到 export -f functionname - Dennis Williamson


我在Linux上有點綠,所以我不確定為什麼它不起作用。但你可以改用一個函數。

在.profile / .bashrc中創建一個新函數:

downloads() { grep  `date '+%d/%b/%Y'` access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '{print $1, $4, $5, $7, $8, $9, $10}' | sort |uniq -c -w15 |sort -n; }

這與別名完全一樣。


6
2017-09-26 23:37



啊! Nagul知道為什麼它不起作用:) - A Dwarf
(+ 1)除非我有正當理由選擇別名而不是函數,否則我實際上更喜歡這個。這比別名的轉義版本更清晰,更明顯。 - nagul


由於別名是在雙引號內定義的,因此 日期 命令在定義別名時執行,並且 $1 變量也得到擴展。您可以在定義別名後查找別名來檢查:

$ alias downloads="grep  `date '+%d/%b/%Y'` access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '{print $1, $4, $5, $7, $8, $9, $10}' | sort |uniq -c -w15 |sort -n"
$ alias downloads
alias downloads='grep  27/Sep/2009 access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '\''{print , , , , , , 0}'\'' | sort |uniq -c -w15 |sort -n'

你應該能夠通過逃避來解決這個問題 日期 打電話和 $1 變量:

$ alias downloads="grep  \`date '+%d/%b/%Y'\` access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '{print \$1, \$4, \$5, \$7, \$8, \$9, \$10}' | sort |uniq -c -w15 |sort -n"
$ alias downloads
alias downloads='grep  `date '\''+%d/%b/%Y'\''` access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '\''{print $1, $4, $5, $7, $8, $9, $10}'\'' | sort |uniq -c -w15 |sort -n'

檢查您是否能夠成功運行此功能。理想情況下,您可以在單引號中定義別名,但別名中單引號的存在會使您的情況變得棘手。


4
2017-09-26 23:36





另一種變化是使用單引號用於外部引用並轉義並引用內部引用。您可以選擇任何一種方法(這一種或一種方法) nagul的 回答)對特定情況做出最不愉快的結果。

alias downloads='grep  $(date '\''+%d/%b/%Y'\'') access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '\''{print $1, $4, $5, $7, $8, $9, $10}'\'' | sort |uniq -c -w15 |sort -n'

你可能會注意到這是什麼 alias 如果你逃脫所有的美元符號,無論如何都打印出來。

我冒昧地改變了反引號 $() 對於 可讀性和多功能性

如果你使用 nagul的 方法(包括外部的雙引號)和 $() 而不是反叛,所有你必須逃脫的是美元符號。

alias downloads="grep  \$(date '+%d/%b/%Y') access.logs  | egrep 2765330645ae47d292c9ceac725d744e.py |awk '{print \$1, \$4, \$5, \$7, \$8, \$9, \$10}' | sort |uniq -c -w15 |sort -n"

這使得易於記憶和非常一致的方法。


3
2017-09-26 23:54





你如何使用從awk獲得的值並將其存儲為變量?這就是我的開始。

alias xx2='xrandr | awk '\''$2=="connected"{s=$1} END{print s}'\'''

這就是我想要做的。

VAR=$(xrandr | awk '$2=="connected"{s=$1} END{print s}'); xrandr --output $VAR --mode 1024x768 --rate 60; xrandr --output LVDS1 --left-of $VAR; xrandr --output LVDS1 --primary; unset VAR;

這是我的第一個想法。在我嘗試打開OMG之後,我看到它沒有為VAR分配任何值。

alias xx2='VAR=$(xrandr | awk '\''$2=="connected"{s=$1} END{print s}'\''); echo $VAR > OMG'


0
2018-06-01 07:07