從標準輸入流中讀取並執行shell指定函式

halu126發表於2022-05-22

巧妙的ohmytmux配置

oh my tmux的配置,發現他們很巧妙的將配置和shell函式放到一個檔案裡

比如切換滑鼠模式的相關配置和shell函式,

# : << EOF
# ...省略其他配置檔案資訊
# toggle mouse
bind m run "cut -c3- ~/.tmux.conf | sh -s _toggle_mouse"
# EOF
#
# _toggle_mouse() {
#   old=$(tmux show -gv mouse)
#   new=""
#
#   if [ "$old" = "on" ]; then
#     new="off"
#   else
#     new="on"
#   fi
#
#   tmux set -g mouse $new
# }
#
# "$@"

 主要功能時 將m鍵繫結上   cut -c3- ~/.tmux.conf | sh -s _toggle_mouse 

cut命令切換註釋

第一個巧妙的地方時   cut -c3- ~/.tmux.conf ,此命令執行的結果是

: << EOF
...省略其他配置檔案資訊
toggle mouse
nd m run "cut -c3- ~/.tmux.conf | sh -s _toggle_mouse"
EOF

_toggle_mouse() {
  old=$(tmux show -gv mouse)
  new=""

  if [ "$old" = "on" ]; then
    new="off"
  else
    new="on"
  fi

  tmux set -g mouse $new
}

"$@"

一個完美的指令碼就出現了!將每一行的前兩個字元去掉,

  1. 使用  '<<EOF'  和  'EOF'  完美的將原來的配置放到多行註釋裡,
  2. 將原來使用 '# '  註釋掉的shell函式 開啟

 sh執行命令

從sh的文件中可以看到 -s 使用執行標準輸入裡執行命令

OPTIONS
       -s        Read commands from the standard input.
STDIN
       The standard input shall be used only if one of the following is true:

        *  The -s option is specified.

        *  The -c option is not specified and no operands are specified.

        *  The script executes one or more commands that require input from standard input (such as a read command that does not redirect its input).

       See the INPUT FILES section.

       When the shell is using standard input and it invokes a command that also uses standard input, the shell shall ensure that  the  standard  input  file  pointer
       points  directly  after  the command it has read when the command begins execution. It shall not read ahead in such a manner that any characters intended to be
       read by the invoked command are consumed by the shell (whether interpreted by the shell or not) or that characters that are not read by the invoked command are
       not  seen  by the shell. When the command expecting to read standard input is started asynchronously by an interactive shell, it is unspecified whether charac‐
       ters are read by the command or interpreted by the shell.

       If the standard input to sh is a FIFO or terminal device and is set to non-blocking reads, then sh shall enable blocking reads on standard  input.  This  shall
       remain in effect when the command completes.

 執行指定函式

從sh的man文件裡沒有看出來可以指定執行指令碼里的哪個函式呢,ohmytmux怎麼讓sh知道執行哪個函式的呢?

注意到cut後的指令碼沒,最後一行是  "$@" 

在shell中$@用來獲得指令碼的所有入參,所以   cut -c3- ~/.tmux.conf | sh -s _toggle_mouse 執行的真正指令碼時

: << EOF
...省略其他配置檔案資訊
toggle mouse
nd m run "cut -c3- ~/.tmux.conf | sh -s _toggle_mouse"
EOF

_toggle_mouse() {
  old=$(tmux show -gv mouse)
  new=""

  if [ "$old" = "on" ]; then
    new="off"
  else
    new="on"
  fi

  tmux set -g mouse $new
}

_toggle_mouse

這樣是不是很明瞭了,

指令碼第一行的  ':' 是shell中的空命令佔位符,它什麼也不幹,永遠返回0

<<EOF   到  EOF定義了一個多行文字,這個多行文字沒有人用, 相當於把原來的配置都註釋掉了

接著 定義一個名字為_toggle_mouse的函式

最後一行  執行該行數

這就是另一個巧妙的地方, 將要執行的函式名當做引數傳給shell,並通過$@將 指定的函式 放到最後一樣

通過這種方式我們就可以方便的執行shell中指定的函式了

參考

oh my tmux github : https://github.com/gpakosz/.tmux

相關文章