AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-289772

user938271's questions

Martin Hope
user938271
Asked: 2020-01-06 00:24:39 +0800 CST

Tmux 中“set-clipboard”选项的“off”和“external”值有什么区别?

  • 4

来自man tmux:

set-clipboard [on | external | off]

        Attempt to set the terminal clipboard content using the xterm(1)
        escape sequence, if there is an Ms entry in the terminfo(5)
        description (see the TERMINFO EXTENSIONS section).

        If set to on, tmux will both accept the escape sequence to create
        a buffer and attempt to set the terminal clipboard.  If set to
        external, tmux will attempt to set the terminal clipboard but
        ignore attempts by applications to set tmux buffers.  If off,
        tmux will neither accept the clipboard escape sequence nor
        attempt to set the clipboard.

        Note that this feature needs to be enabled in xterm(1) by setting
        the resource:

              disallowedWindowOps: 20,21,SetXprop

        Or changing this property from the xterm(1) interactive menu when
        required.

这就是我理解文档的方式;当 Tmux 接收到使用Ms外部终端能力编码的序列时:

  • 如果set-clipboard设置为on,则序列用于设置终端剪贴板和Tmux 缓冲区

  • 如果set-clipboard设置为off,则该序列既不用于设置终端剪贴板也不用于设置Tmux 缓冲区

  • 如果set-clipboard设置为external,则该序列用于设置终端剪贴板,而不是Tmux 缓冲区

我正在使用 XTerm(补丁 322),$TERM设置为xterm-256color,这是它的terminfo 描述,由$ infocmp -1x xterm-256color. 特别是,它的Ms功能设置如下:

Ms=\E]52;%p1%s;%p2%s\007

我里面只有这 3 行~/.Xresources:

XTerm*termName: xterm-256color
XTerm*disallowedWindowOps: 20,21,SetXprop
XTerm*selectToClipboard: true

我在没有配置的情况下启动 Tmux:

$ tmux -Lx -f/dev/null

我设置set-clipboard为on:

$ tmux set -s set-clipboard on

printf我通过包含文本向 Tmux 发送一个 OSC 52 序列test on:

$ printf '\e]52;c;%s\007' $(printf 'test on' | base64)

结果是 Tmux 创建了一个内部缓冲区,并将 OSC 52 序列发送到 XTerm,XTerm 填充了它的剪贴板test on:

$ tmux lsb
buffer0: 7 bytes: "test on"

$ xsel -b
test on

现在我重置set-clipboard为off:

$ tmux set -s set-clipboard off

printf我通过包含文本向 Tmux 发送一个 OSC 52 序列test off:

$ printf '\e]52;c;%s\007' $(printf 'test off' | base64)

这一次,Tmux 没有创建新的内部缓冲区,也没有将 OSC 52 序列发送到 XTerm:

$ xsel -b
test on

$ tmux lsb
buffer0: 7 bytes: "test on"

否则,这 2 个 shell 命令的输出之一将包括test off.


最后,我重置set-clipboard为external:

$ tmux set -s set-clipboard external

printf我通过包含文本向 Tmux 发送一个 OSC 52 序列test external:

$ printf '\e]52;c;%s\007' $(printf 'test external' | base64)

Tmux 没有创建新的内部缓冲区,也没有将 OSC 52 序列发送到 XTerm:

$ xsel -b
test on

$ tmux lsb
buffer0: 7 bytes: "test on"

否则,这 2 个 shell 命令的输出之一将包括test external.


我理解设置set-clipboard为on和时的结果off,但我不理解设置为 时的结果external。基于 Tmux 手册页的这句话:

如果设置为 external,tmux 将尝试设置终端剪贴板,但忽略应用程序设置 tmux 缓冲区的尝试。

我本来希望 Tmux 将 OSC 52 序列发送到 XTerm,而不创建内部缓冲区。实际上,它不会创建内部缓冲区(预期),但也不会将 OSC 52 序列发送到 XTerm(意外)。

我一定误解了这句话。我可以进行哪个实验来观察值external和之间的差异off?

tmux
  • 1 个回答
  • 528 Views
Martin Hope
user938271
Asked: 2019-11-07 01:15:54 +0800 CST

如何在 zsh 命令中引用路径尾部的根?

  • 3

我经常克隆一个 git 存储库,然后进入它的根目录。例如:

$ git clone https://github.com/hpjansson/chafa && cd chafa

为了让这更容易一点,我有一个 zsh 缩写 – cc– 扩展为&& cd !#:2:t:

typeset -Ag abbrev
abbrev=(
  'G' '| grep -v grep | grep'
  'L' '2>&1 | less'
  'V' '2>&1 | vipe >/dev/null'
  'ac' '| column -t'
  'bl' '; tput bel'
  'cc' '&& cd !#:2:t'
  'fl' "| awk '{ print $"
  'ne' '2>/dev/null'
  'pf' "printf -- '"
  'sl' '>/dev/null 2>&1'
  'tl' '| tail -20'
)
__abbrev_expand() {
  emulate -L zsh
  setopt EXTENDED_GLOB
  local MATCH
  LBUFFER=${LBUFFER%%(#m)[a-zA-Z]#}
  if [[ "${LBUFFER: -1}" == ' ' ]]; then
    LBUFFER+=${abbrev[$MATCH]:-$MATCH}
    if [[ $MATCH = 'fl' ]]; then
      RBUFFER="}'"
    elif [[ $MATCH = 'pf' ]]; then
      RBUFFER="\n'"
    fi
  else
    LBUFFER+=$MATCH
  fi
  zle self-insert
}
zle -N __abbrev_expand
bindkey ' ' __abbrev_expand
bindkey -M isearch ' ' self-insert

!#指当前命令行,如man zshexpn(section HISTORY EXPANSION, subsection Event Designators) 中所述:

!# 参考目前输入的命令行。该行被视为完整,直到包含!#引用的单词之前的单词。

:2指的是命令行上的第二个单词(这是我键入$ git clone命令时的 url):

n 第 n 个参数。

并:t指那个词的尾巴:

t 删除所有前导路径名组件,留下尾部。这就像basename.


通常,我会git clone在命令行上键入,然后复制粘贴项目的 url,然后插入一个空格cc和另一个空格,这会给出所需的命令。

但是,有时,我复制粘贴的 url 以扩展名结尾.git。当发生这种情况时,扩展!#:2:t包含一个不需要的.git扩展:

$ git clone https://github.com/hpjansson/chafa.git cc
→
$ git clone https://github.com/hpjansson/chafa.git && cd !#:2:t
→
$ git clone https://github.com/hpjansson/chafa.git && cd chafa.git
cd: no such file or directory: chafa.git

一种解决方案是也使用:r修饰符来删除.git扩展名:

r 删除保留根名称的文件扩展名。没有文件扩展名的字符串不会被更改。文件扩展名.后面是任意数量的字符(包括零),它们既不是 . 也不是 / ,并且继续到字符串的末尾。例如,扩展名foo.orig.c是.c,并且 dir.c/foo没有扩展名。

                                                               vv
$ git clone https://github.com/hpjansson/chafa.git && cd !#:2:t:r
→
$ git clone https://github.com/hpjansson/chafa.git && cd chafa

但是,如果路径不以.git扩展名结尾,则扩展失败并且git命令和cd命令都不会被执行。

这是一个说明问题的最小示例:

$ echo /foo/bar.baz !#:1:t:r
/foo/bar.baz bar

$ echo /foo/bar !#:1:t:r
zsh: modifier failed: r

第一个命令成功,因为最后一个路径组件包含扩展名.baz,但第二个命令失败,因为不再有扩展名。OTOH,在 bash 中4.3.48,两个命令都按预期工作。

我不明白为什么:r没有扩展时会失败,因为它的文档包含这句话:

没有文件扩展名的字符串不会被更改。

它并不是说使用:r不包含扩展名的字符串是错误的。


我尝试了另一种方法;:s使用修饰符删除扩展名。我认为这需要设置HIST_SUBST_PATTERN选项:

setopt HIST_SUBST_PATTERN

使用此选项,可以编写:s/.*删除扩展名:

                          vvvvv
$ echo /foo/bar.baz !#:1:t:s/.*
/foo/bar.baz bar

它在有扩展名时有效,但在没有扩展名时再次失败:

$ setopt HIST_SUBST_PATTERN
$ echo /foo/bar !#:1:t:s/.*
zsh: substitution failed

是否有一个修饰符序列可以同时引用barin/foo/bar.baz和 to barin /foo/bar?

我正在使用zsh 5.7.1-dev-0 (x86_64-pc-linux-gnu).

zsh
  • 1 个回答
  • 425 Views
Martin Hope
user938271
Asked: 2019-09-14 03:19:52 +0800 CST

使用 Vim 作为手册页时如何防止手册页的名称被截断?

  • 1

考虑这个 shell 命令:

$ MANPAGER='vim -Nu NONE -R -' man git-credential-cache

它使man(1)显示git-credential-cache(1)在 Vim 中的手册页。

但是,手册页的名称(显示在缓冲区的第一行)是GIT-CREDENTIAL-CAC(1). 请注意HE名称末尾的缺失:

git-credential-cache 手册页的名称缺少最后两个字符

我希望这个名字改为:

GIT-CREDENTIAL-CACHE(1)
                  ^^

我跑去strace(1)查看使用了哪些系统调用man(1):

$ MANPAGER='vim -Nu NONE -R -' strace -o log man git-credential-cache

在日志文件的末尾,我可以看到一个read(2)和write(2)系统调用,使用缓冲区名称GIT-CREDENTIAL-CAC(1):

read(7, "GIT-CREDENTIAL-CAC(1)           "..., 4096) = 2720
...
write(8, "GIT-CREDENTIAL-CAC(1)           "..., 2720) = 2720

因此,似乎是man(1)而不是vim(1)截断了手册页的名称。

这是日志文件的完整内容,另一个日志文件包含相同strace(1)命令的输出,但带有用于跟踪子进程的附加-f参数,以及通向该man(1)进程的进程树:

$ pstree -lsp $(pidof man)
systemd(1)---lightdm(947)---lightdm(1114)---upstart(1123)---sh(1324)---xfce4-session(1335)---xfce4-panel(1347)---panel-8-whisker(1396)---xterm(22546)---bash(22547)---strace(23182)---man(23184)---vim(23194)

有没有办法防止man(1)截断GIT-CREDENTIAL-CACHE(1)成GIT-CREDENTIAL-CAC(1)?

我问这个问题的原因是因为截断会导致在使用Neovim man 插件时显示错误消息:

            ┌ Taken from `:h man.vim` in Neovim
            ├────────┐
$ MANPAGER='nvim +Man!' man git-credential-cache
man.vim: command error (7) man -w git-credential-cac: No manual entry for git-credential-cac

由于手册页名称被截断而导致 Neovim 中的错误


环境:

$  lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.6 LTS
Release:        16.04
Codename:       xenial

$ man --version
man 2.7.5

$ vim --version | head -n2
VIM - Vi IMproved 8.1 (2018 May 18, compiled Sep  3 2019 11:05:36)
Included patches: 1-1967

$ nvim --version | head -n1
NVIM v0.4.0-1856-g82d52b229
vim
  • 1 个回答
  • 130 Views
Martin Hope
user938271
Asked: 2019-08-09 13:12:49 +0800 CST

为什么我需要插入 12 个字符来清除这个 bash 命令行?

  • 15

我打开一个 xterm 终端(80 列 x 24 行),然后运行$ bash --norc --noprofile​​,然后$ tty获取终端的文件名:输出为/dev/pts/9.

从另一个终端我运行:

$ printf foo >/dev/pts/9

foo打印在第一个终端的 shell 命令行上。
如果我按下C-u运行unix-line-discard(由 给出的函数名称$ bind -P | grep -i c-u),foo则不会被删除。
如果我插入 11 个空格并按C-u,则空格会被删除,但不会foo。
如果我插入 12 个空格并按C-u,则空格也会被删除foo。

在此处输入图像描述

foo为什么当我的光标在它后面时我按下时不能删除C-u,为什么我需要插入12个字符才能删除它?


环境:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.6 LTS
Release:        16.04
Codename:       xenial

$ bash --version | head -n1
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

$ xterm -version
XTerm(322)
bash terminal-emulator
  • 1 个回答
  • 5144 Views
Martin Hope
user938271
Asked: 2019-02-27 05:11:51 +0800 CST

为什么 gawk 在来自输入数据时将“0123”视为十进制数?

  • 5

根据$ man gawk,该strtonum()函数可以将字符串转换为数字:

strtonum(str) 检查 str,并返回其数值。如果 str 以前导 0 开头,则将其视为八进制数。如果 str 以前导 0x 或 0X 开头,则将其视为十六进制数。否则,假设它是一个十进制数。

如果字符串以 开头0,则该数字被视为八进制,而如果它以它开头,0x则被视为十六进制。

我已经运行了这些命令来检查我对函数的理解:

$ awk 'END { print strtonum("0123") }' <<<''
83

$ awk 'END { print strtonum("0x123") }' <<<''
291

该字符串"0123"被正确地视为包含八进制数并转换为十进制数83。同样,字符串"0x123"被正确地视为包含十六进制数并转换为十进制数291。

现在,如果我运行相同的命令,但将数字字符串从程序文本移动到输入数据,会发生以下情况:

$ awk 'END { print strtonum($1) }' <<<'0123'
123

$ awk 'END { print strtonum($1) }' <<<'0x123'
291

我理解与前面命令相同的第二个结果,但我不理解第一个。为什么 gawk 现在将0123其视为十进制数,即使它以0八进制数的前导开头?

我怀疑它与strnum 属性有关,因为出于某种原因1,gawk 将此属性赋予0123但不赋予0x123:

$ awk 'END { print typeof($1) }' <<<'0123'
strnum

$ awk 'END { print typeof($1) }' <<<'0x123'
string

1这可能是由于awk 实现之间的差异:

澄清一下,只有来自几个来源的字符串(这里引用 POSIX 规范): [...] 如果它们的值恰好是数字(允许前导和尾随空格, 实现之间有所不同),则将被视为数字字符串支持十六进制,八进制,inf,nan ...)。


我正在使用 gawk version 4.2.62,输出$ awk -V为:

GNU Awk 4.2.62, API: 2.0 (GNU MPFR 3.1.4, GNU MP 6.1.0)
input gawk
  • 1 个回答
  • 344 Views
Martin Hope
user938271
Asked: 2018-11-29 13:06:05 +0800 CST

当 zle 小部件“edit-command-line”启动时,如何防止 Vim 将 Cj 翻译成 Cm?

  • 3

我的代码中有以下代码~/.zshrc:

autoload -Uz edit-command-line
zle -N edit-command-line
bindkey '^X^E' edit-command-line

它将edit-command-linezle 小部件绑定到 keysequence C-x C-e。该小部件在man zshcontrib(部分 ZLE FUNCTIONS,小节Widgets)中进行了描述:

edit-command-line 使用您的可视化编辑器编辑命令行,就像在 ksh 中一样。

          bindkey -M vicmd v edit-command-line

目的是能够编辑当前的 shell 命令行,在默认编辑器中,通过按C-x C-e,类似于 readline 函数edit-and-execute-command所做的(man bash, section READLINE, subsection Commands for Manipulating the History)。

edit-and-execute-command (C-xC-e) 在当前命令行调用编辑器,并将结果作为 shell 命令执行。Bash 尝试按顺序调用 $VISUAL、$EDITOR 和 emacs 作为编辑器。

我的默认编辑器是 Vim 8.1(包括补丁1-538)。我有 Vim 映射,使用键C-h, C-j, C-k, C-l, 将焦点移动到相邻窗口。它们可以归结为:

nnoremap <c-h> :<c-u>wincmd h<cr>
nnoremap <c-j> :<c-u>wincmd j<cr>
nnoremap <c-k> :<c-u>wincmd k<cr>
nnoremap <c-l> :<c-u>wincmd l<cr>

它们都在常规 Vim 实例中按预期工作(通过执行开始$ vim)。但是C-j当 Vim 由edit-command-line.

当我在 shell 命令行上按下C-x C-ewhile 时,zsh 会启动 Vim。如果我通过执行拆分窗口:split,然后按C-k移动到顶部窗口,我得到两个窗口,焦点移动到顶部。但是,如果我按下C-j返回底部窗口,则什么也不会发生。

我不知道这是否是问题的原因,但如果我尝试C-j在 Vim 缓冲区中插入一个文字(通过按C-v C-j),^M则会显示(回车符符号)。在一个常规的 Vim 实例中(通过执行 开始$ vim),插入一个字面值C-j会导致插入符号为^@(a NUL) 的字符。

我可以用这个最小值重现这个问题~/.zshrc:

export EDITOR=vim
autoload -Uz edit-command-line
zle -N edit-command-line
bindkey '^X^E' edit-command-line

这个最小的~/.vimrc:

nnoremap <c-j> :echom 'C-j has been pressed'<cr>

在 zsh 命令行上按下C-x C-e启动 Vim,然后按下C-j应该打印并记录消息:

C-j has been pressed

但什么也没有发生。

我无法在 bash 或 Neovim ( v0.3.2-752-g4d7c7f9) 中重现该问题。此外,在 Vim 中插入文字C-j,当后者在按下 后从 bash 启动时C-x C-e,会导致 NUL ( ^@)。在按下 后从 bash 或 zsh 启动 Neovim 时也是如此C-x C-e。

┌────────┬──────┬─────┐
│        │ bash │ zsh │
├────────┼──────┼─────┤
│ Vim    │ ^@   │ ^M  │
├────────┼──────┼─────┤
│ Neovim │ ^@   │ ^@  │
└────────┴──────┴─────┘

我想可能是某些 Vim 终端选项没有正确配置,所以我捕获了以下输出:

:set termcap

从 Vim 开始于$ vim,从 Vim 开始于C-x C-e。但是两种情况下的输出是相同的:

--- Terminal codes ---

  t_AL=^[[%p1%dL      t_DL=^[[%p1%dM      t_mr=^[[7m          t_se=^[[27m         t_us=^[[4m
  t_al=^[[L           t_dl=^[[M           t_ms=y              t_Sf=               t_ut=
  t_bc=               t_EC=               t_nd=^[[C           t_SH=               t_vb=^[g
  t_BE=               t_EI=^[[2 q         t_op=^[[39;49m      t_SI=^[[6 q         t_vi=^[[?25l
  t_BD=               t_fs=^G             t_RF=               t_Si=               t_VS=
  t_cd=^[[J           t_GP=               t_RB=               t_so=^[[7m          t_vs=^[[34l
  t_ce=^[[K           t_IE=               t_RC=               t_SR=^[[4 q         t_WP=
  t_cl=^[[H^[[J       t_IS=               t_RI=^[[%p1%dC      t_sr=^[M            t_WS=
  t_Ce=               t_ke=^[[?1l^[>      t_Ri=               t_ST=               t_xn=y
  t_Co=256            t_ks=^[[?1h^[=      t_RS=               t_Te=               t_xs=
  t_CS=               t_le=^H             t_RT=               t_Ts=               t_ZH=^[[3m
  t_CV=               t_mb=^[[5m          t_RV=               t_ts=^[]0;          t_ZR=^[[23m
  t_da=               t_md=^[[1m          t_Sb=               t_u7=               t_8f=
  t_db=               t_me=^[[0m          t_SC=               t_ue=^[[24m         t_8b=
  t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m
  t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m
  t_cm=^[[%i%p1%d;%p2%dH
  t_Cs=^[]12;%p1%s^G
  t_cs=^[[%i%p1%d;%p2%dr
  t_te=^[[2 q^[[?1004l^[[?1049l
  t_ti=^[[2 q^[[?1004h^[[?1049h
  t_ve=^[[34h^[[?25h

--- Terminal keys ---

t_#2 <S-Home>    ^[[1;2H   t_k6 <F6>        ^[[17~    t_kh <Home>      ^[[1~          <ð>        ^[p
t_#4 <S-Left>    ^[[1;2D   t_k7 <F7>        ^[[18~    t_kl <Left>      ^[OD           <ô>        ^[t
t_%i <S-Right>   ^[[1;2C   t_k8 <F8>        ^[[19~    t_kr <Right>     ^[OC           <õ>        ^[u
t_*7 <S-End>     ^[[1;2F   t_k9 <F9>        ^[[20~    t_ku <Up>        ^[OA           <ù>        ^[y
t_@7 <End>       ^[[4~     t_k; <F10>       ^[[21~         <á>        ^[a            <ú>        ^[z
t_F1 <F11>       ^[[23~    t_kB <S-Tab>     ^[[Z           <â>        ^[b            <Mouse>     ^[[M
t_F2 <F12>       ^[[24~    t_kD <Del>       ^[[3~          <ä>        ^[d            <S-F18>     ^[[O
t_k1 <F1>        ^[OP      t_kI <Insert>    ^[[2~          <å>        ^[e            <S-F19>     ^[[I
t_k2 <F2>        ^[OQ      t_kN <PageDown>  ^[[6~          <æ>        ^[f            <xUp>       ^[[1;*A
t_k3 <F3>        ^[OR      t_kP <PageUp>    ^[[5~          <ç>        ^[g            <xDown>     ^[[1;*B
t_k4 <F4>        ^[OS      t_kb <BS>        ^?             <í>        ^[m            <xLeft>     ^[[1;*D
t_k5 <F5>        ^[[15~    t_kd <Down>      ^[OB           <î>        ^[n            <xRight>    ^[[1;*C

bash 和 zsh的输出$ stty -a也是相同的:

speed 38400 baud; rows 33; columns 119; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff
-iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -flusho -extproc

我正在使用zsh 5.6.2-dev-1 (x86_64-pc-linux-gnu).

是否应该设置 Vim 或 zsh 选项以防止 Vim在由 zle 小部件启动时转换C-j为?C-medit-command-line

zsh vim
  • 1 个回答
  • 229 Views
Martin Hope
user938271
Asked: 2018-10-31 20:19:47 +0800 CST

为什么文件名生成失败会使 zsh 停止处理脚本?

  • 6

我试图编写一个简短的脚本来编写在以下位置找到的所有可执行程序$PATH:

for dir in $(tr ':' ' ' <<<"${PATH}"); do
  for pgm in $dir/*; do
    if command -v "${pgm}" >/dev/null 2>&1; then
      echo "${pgm}"
    fi
  done
done | sort >file

在 bash 中,它按预期工作,但一旦文件名生成在内部循环中失败,zsh 就会停止处理脚本:

for pgm in $dir/*; do
           ^^^^^^
  ...
done

结果,由于 my$PATH包含一个不包含任何文件 ( /usr/local/sbin) 的目录,因此在 zsh 中,脚本无法写入随后在目录中找到的可执行文件。

这是显示相同问题的另一个代码:

for f in /not_a_dir/*; do
  echo 'in the loop'
done
echo 'after the loop'

在 bash 中,此命令输出:

in the loop
after the loop

并退出代码0。

在 zsh 中,相同的命令输出:

no matches found: /not_a_dir/*

并退出代码1。

shell 之间的行为差​​异似乎来自nomatch选项,该选项在man zshoptions:

NOMATCH (+3) <C> <Z>

如果用于文件名生成的模式没有匹配项,则打印错误,而不是在参数列表中保持不变。这也适用于初始~或=.

并且还在man zshexpn(文件名生成部分)中进行了解释:

该词被替换为与模式匹配的排序文件名列表。如果没有找到匹配的模式,shell 会给出一个错误信息,除非设置了 NULL_GLOB 选项,在这种情况下这个词会被删除;或者除非未设置 NOMATCH 选项,在这种情况下,单词保持不变。

因为如果我取消设置nomatch,zsh 的行为就像 bash:

unsetopt nomatch
for f in /not_a_dir/*; do
  echo 'in the loop'
done
echo 'after the loop'

现在我了解了 bash 和 zsh 之间的行为差​​异,以及为什么脚本会在 zsh 中引发错误,但我想了解为什么文件名生成失败会使 zsh 立即停止处理脚本。因此,我尝试通过用失败的命令(通过执行not_a_cmd)替换失败的文件名生成来重现相同的问题:

for f in ~/*; do
  not_a_cmd
done
echo 'after the loop'

但是这个脚本的输出在两个 shell 中几乎是相同的(除了由于 引起的错误消息not_a_cmd)。特别是,两个 shell 都打印:

after the loop

并且两个 shell 都以代码退出0。

为什么文件名生成失败(如for f in /not_a_dir/*)会使 zsh 停止处理脚本,而不是失败的命令(如not_a_cmd)?

我正在使用zsh 5.6.2-dev-0 (x86_64-pc-linux-gnu).

zsh
  • 1 个回答
  • 234 Views
Martin Hope
user938271
Asked: 2018-10-25 17:52:42 +0800 CST

设置了`separate-sections`样式时,如何使zsh将手册部分传递给man命令?

  • 4

当通过在 zsh 命令行上按 Tab 来请求完成时,如果group-name样式设置为空字符串,则可以根据它们的标记对匹配项进行分组:

autoload -Uz compinit
compinit
zstyle ':completion:*' menu select
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%d'

在命令的情况下,如果将样式设置为标签$ man,则可以进一步划分匹配项:separate-sectionstruemanuals

autoload -Uz compinit
compinit
zstyle ':completion:*' menu select
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%d'
zstyle ':completion:*:manuals' separate-sections true

因此,如果我在 之后按 Tab $ man write,完成系统会建议这些匹配:

$ man write
manual page, section 1 (general commands)
write
manual page, section 2 (system calls)
write   writev

如果我write在第一个列表中选择匹配项,则会$ man打开write手册第一部分的页面。

但是如果我write在第二个列表中选择匹配项,$ man仍然会打开write第一部分的页面,而列表的描述提到了手册的第二部分。

separate-sections设置样式时,是否可以使 zsh 将相关手册部分传递给 man 命令?

我正在使用zsh 5.6.2-dev-0 (x86_64-pc-linux-gnu).

zsh autocomplete
  • 1 个回答
  • 512 Views
Martin Hope
user938271
Asked: 2018-10-23 08:35:25 +0800 CST

如何在手册页中搜索包含连字符的模式?

  • 11

我正在尝试找到一个命令来搜索所有手册页中包含连字符的模式。

我查看了man man,发现了以下 3 个选项:

-K,--global-apropos

在所有手册页中搜索文本。这是一种蛮力搜索,可能需要一些时间;如果可以,您应该指定一个部分以减少需要搜索的页面数。--regex如果使用该选项,搜索词可能是简单的字符串(默认)或正则表达式。

-w, --where, --path,--location

实际上并不显示手册页,而是打印将被格式化的源 nroff 文件的位置。

-S list, -s list,t--sections=list

List 是以冒号或逗号分隔的订单特定手册部分的搜索列表。此选项会覆盖$MANSECT环境变量。(-s拼写是为了与 System V 兼容。)

我试图将它们结合起来搜索模式mark-modified-lines,这是一个 readline 选项,如下所述man bash:

$ man -s1 -Kw mark-modified-lines

但它没有找到任何页面:

No manual entry for mark-modified-lines

并且命令与代码一起退出16。
我认为该命令的语法可能是错误的,但似乎并非如此,因为该命令正确地找到了我系统上包含以下单词的 5 个手册页guitar:

$ man -s1 -Kw guitar

  /usr/share/man/man1/ffmpeg-all.1.gz
  /usr/share/man/man1/ffserver-all.1.gz
  /usr/share/man/man1/ffplay-all.1.gz
  /usr/share/man/man1/ffmpeg-filters.1.gz
  /usr/share/man/man1/ffprobe-all.1.gz

我认为也许这个词中的连字符引起了问题。在man bash中,我找到了--regex描述如下的选项:

--regex

将名称或描述的任何部分与每个页面参数匹配的所有页面显示为正则表达式,如apropos(1). 由于在搜索正则表达式时通常没有合理的方法来选择“最佳”页面,因此此选项意味着-a.

我尝试使用此选项并用mark-modified-linesregex替换单词mark.modified.lines,其中连字符本身被替换为.应该匹配任何字符的元字符:

$ man -s1 -Kw --regex 'mark.modified.lines'

它仍然不打印任何页面,而我知道文本写在bash手册页中。

正则表达式中的元字符.似乎按预期解析,因为此命令:

$ man -s1 -Kw --regex 'mark.mo'

印刷:

  /usr/share/man/man1/x11perfcomp.1.gz
  /usr/share/man/man1/xditview.1.gz

并且这 2 个联机帮助页 ( x11perfcomp, xditview) 都由正则表达式匹配mark.mo。更具体地说,man x11perfcomp包含这一行:

Mark Moraes wrote the original scripts to compare servers.
^^^^^^^

并man xditview包含这一行:

    Mark Moraes (University of Toronto)
    ^^^^^^^

但是,man -s1 -Kw --regex 'mark.mo'不打印 bash 手册页:

/usr/share/man/man1/bash.1.gz

虽然我期望它会,因为它包含这一行:

mark-modified-lines (Off)
^^^^^^^

是否可以在手册页中搜索包含连字符的模式?

man
  • 1 个回答
  • 997 Views
Martin Hope
user938271
Asked: 2018-09-24 14:57:31 +0800 CST

如何打印 zsh 参数的所有属性?

  • 4

我可以将-U属性赋予非关联数组,使其不能包含重复元素:

% declare -U path
% path=( ~/bin $path )
% path=( ~/bin $path )
% echo $path

在这里,即使我两次添加~/bin到数组path中,后者也只包含一个~/bin元素。

我正在寻找一种方法来打印可以在分配期间赋予参数的所有属性,包括此-U属性。

我查看了 中的typeset命令man zshbuiltins,并找到了以下摘录:

除非使用 name=value 进行赋值,否则使用 +m 会强制打印匹配的参数及其属性,即使在函数内部也是如此。

所以,我尝试执行这些命令:

% declare -U path
% declare +m 'path'

谁的输出是:

array path

虽然它告诉我参数的类型(这里是一个数组),但它并没有告诉我它具有-U属性。

是否有另一个命令可以打印参数的所有属性?

zsh
  • 1 个回答
  • 358 Views
Martin Hope
user938271
Asked: 2018-09-15 11:18:08 +0800 CST

在编译 `tmux` 包期间,如何设置 `$ tmux -V` 报告的版本号?

  • 0

我正在通过如下脚本从其源代码编译tmux :

set -e
DIR="${HOME}/Programs/"
build() {
  [[ -d "${DIR}" ]] || mkdir -p "${DIR}"
  cd "${DIR}"
  if [[ ! -d tmux ]]; then
    git clone https://github.com/tmux/tmux
  fi
  cd tmux
  git stash
  git checkout master
  git pull
  make clean; make distclean
  sh autogen.sh
  ./configure
  make
}
install() {
  dpkg -r tmux
  checkinstall --pkgname tmux --pkgversion '9999:9999.9999' -y
}
build
install

它按预期编译和安装 tmux。
但仍然存在一个问题,即报告的版本$ tmux -V:

$ tmux -V
tmux master

它报告tmux master,虽然我更愿意tmux X.Y,X.Y是最新版本的版本。例如,目前最新版本是2.8,所以我想$ tmux -V输出tmux 2.8.

有什么办法可以改变这个输出吗?

我查看了 的输出./configure --help,并搜索了一个选项来设置 tmux 进程的版本,但找不到。

目前,我sed在我的脚本中包含了一个命令,以便它自动编辑文件configure.ac,并分配一个大版本号99.99(我不知道如何以编程方式获取最新版本的版本号):

sh autogen.sh
sed -i 's/AC_INIT(tmux, master)/AC_INIT(tmux, 99.99)/' configure.ac
./configure

有没有更好的办法?


之所以问这个问题是因为我用的是tmux-open$ tmux -V插件,输出的时候没有按预期工作tmux master。

后者使用这行代码来确定当前 tmux 进程的版本:

$ tmux_version="$(tmux -V | cut -d ' ' -f 2)"

然后插件使用这个变量来确定安装键绑定的命令的语法。

我的机器上没有安装键绑定,我认为这是由于$ tmux -V. 因为如果我在插件中替换这一行:

if [[ $tmux_version == $1 ]]

用这一行:

if [[ $tmux_version == $1 ]] || [[ $tmux_version == 'master' ]]

然后插件正确安装其键绑定。

tmux
  • 1 个回答
  • 166 Views
Martin Hope
user938271
Asked: 2018-05-21 18:06:20 +0800 CST

如何从陷阱中启动 Vim 并在暂停后仍然能够恢复它?

  • 2

我的代码中有以下代码~/.zshrc:

nv() (
  if vim --serverlist | grep -q VIM; then
    if [[ $# -eq 0 ]]; then
      vim
    elif [[ $1 == -b ]]; then
      shift 1
      IFS=' '
      vim --remote "$@"
      vim --remote-send ":argdo setl binary ft=xxd<cr>"
      vim --remote-send ":argdo %!xxd<cr><cr>"
    elif [[ $1 == -d ]]; then
      shift 1
      IFS=' '
      vim --remote-send ":tabnew<cr>"
      vim --remote "$@"
      vim --remote-send ":argdo vsplit<cr>:q<cr>"
      vim --remote-send ":windo diffthis<cr>"
    elif [[ $1 == -o ]]; then
      shift 1
      IFS=' '
      vim --remote "$@"
      vim --remote-send ":argdo split<cr>:q<cr><cr>"
    elif [[ $1 == -O ]]; then
      shift 1
      IFS=' '
      vim --remote "$@"
      vim --remote-send ":argdo vsplit<cr>:q<cr><cr>"
    elif [[ $1 == -p ]]; then
      shift 1
      IFS=' '
      vim --remote "$@"
      vim --remote-send ":argdo tabedit<cr>:q<cr>"
    elif [[ $1 == -q ]]; then
      shift 1
      IFS=' '
      vim --remote-send ":cexpr system('$*')<cr>"
    else
      vim --remote "$@"
    fi
  else
    vim -w /tmp/.vimkeys --servername VIM "$@"
  fi
)

它的目的是安装一个nv函数来启动一个 Vim 实例以及一个 Vim 服务器。如果 Vim 服务器已经在运行,该函数应该将它收到的文件参数发送到服务器。

到目前为止,它运作良好。


我的中有以下映射~/.vimrc:

nno  <silent><unique>  <space>R  :<c-u>sil call <sid>vim_quit_reload()<cr>
fu! s:vim_quit_reload() abort
    sil! update
    call system('kill -USR1 $(ps -p $(ps -p $$ -o ppid=) -o ppid=)')
    qa!
endfu

其目的是通过向USR1父 shell 发送信号来重新启动 Vim。

我也有以下陷阱,~/.zshrc当它捕捉到信号时它会重新启动 Vim USR1。

catch_signal_usr1() {
  trap catch_signal_usr1 USR1
  clear
  vim
}
trap catch_signal_usr1 USR1

到目前为止,它也运作良好。


但我注意到,如果我C-z在 shell 中按 , 挂起 Vim,即使 Vim 进程仍在运行,我也无法恢复它(使用$ fg),因为 shell 没有任何工作。

zshrc这是我能够重现该问题的最小值:

catch_signal_usr1() {
  trap catch_signal_usr1 USR1
  vim
}
trap catch_signal_usr1 USR1
func() {
  vim
}

这是一个最小的vimrc:

nnoremap  <space>R  :call Func()<cr>
function! Func()
    call system('kill -USR1 $(ps -p $(ps -p $$ -o ppid=) -o ppid=)')
    qa!
endfunction

如果我使用以下函数启动 Vim:

$ func

然后,按 重新启动 Vim Space R,然后按 挂起它C-z,一旦我回到 shell,我可以看到 Vim 进程正在运行:

$ ps -efH | grep vim
user     24803 24684 10 03:56 pts/9    00:00:01             vim
user     24990 24684  0 03:56 pts/9    00:00:00             grep vim

但我无法恢复它:

$ fg
fg: no current job

如果我使用$ vim命令而不是$ func函数来启动 Vim,我可以重新启动 Vim 进程,将其挂起并恢复它。问题似乎来自功能$ func。


这是我的环境:

  • vim --version: VIM - Vi IMproved 8.1 由用户编译
  • 操作系统:Ubuntu 16.04.4 LTS
  • 终端模拟器:rxvt-unicode v9.22
  • 终端多路复用器:tmux 2.7
  • $TERM: tmux-256color
  • 外壳:zsh 5.5.1

如何从函数启动 Vim 并在挂起后仍然能够恢复它?


编辑:

更多信息:

(1) 当您键入 Ctrl+Z 时,您的终端上会显示什么?

当我键入时没有显示任何内容C-z。

(A) 如果我用下面的命令启动 Vim,$ vim按下 后会显示C-z:

ubuntu% vim

zsh: suspended  vim

我可以用 恢复$ fg。


(B) 如果我使用以下函数启动 Vim $ func:

ubuntu% func
zsh: suspended  func

我也可以用$ fg.


(C) 如果我使用$ vim命令启动 Vim,然后按 重新启动 Vim Space R:

ubuntu% vim
zsh: suspended  catch_signal_usr1

同样,我可以继续使用$ fg.


(D) 但是,如果我使用该$ func功能启动 Vim 并按 重新启动它Space R:

ubuntu% func
ubuntu%

当我回到提示符时没有显示任何内容,并且我无法使用$ fg.


(2) 如果你输入jobs,你的shell 会说什么?

$ jobs没有输出。这是前四种情况下的输出:

(一个)

ubuntu% jobs
[1]  + suspended  vim

(乙)

ubuntu% jobs
[1]  + suspended (signal)  func

(C)

ubuntu% jobs
[1]  + suspended (signal)  catch_signal_usr1

(四)

ubuntu% jobs
ubuntu%

似乎这个问题zsh至少特定于 up to 5.5.1,因为我无法用 bash 重现4.4。

zsh vim
  • 1 个回答
  • 580 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve