我有一些简单的shell代码将在控制台中执行,但不会在脚本中执行。以下是我缺乏进展的说明。
我正在尝试隔离触摸屏的xinput设备号。这些行在控制台上工作:
% NAME="Atmel maXTouch Digitizer"
% DEVICE=`xinput | grep "$NAME" | grep -o "id=[0-9]+" | tr -d id=`
% echo Device found: $DEVICE
Device found: 12
在脚本中,这些确切的行不会产生任何结果:
% touchscreen
Device found:
这个单行代码产生相同的值:
% echo `xinput | grep "Atmel maXTouch Digitizer" | grep -o "id=[0-9]+" | tr -d id=`
12
在脚本中,单行也只生成一个空行,这可能会导致bad quoting消失。
为了澄清发生了什么,我打破了代码。在控制台,一切都是金色的:
% NAME="Atmel maXTouch Digitizer"
% LINE=`xinput | grep "$NAME"`
% echo $LINE
⎜ ↳ Atmel Atmel maXTouch Digitizer id=12 [slave pointer (2)]
% PART=`echo $LINE | grep -o "id=[0-9]+"`
% echo $PART
id=12
% DEVICE=`echo $PART | tr -d id=`
% echo Device found: $DEVICE
Device found: 12
在一个脚本中,它获得了第一个grep,但没有进一步:
% touchscreen
⎜ ↳ Atmel Atmel maXTouch Digitizer id=12 [slave pointer (2)]
Device found:
如果有任何strange subshell stuff正在进行,我预计第一个grep也不会工作。
反引号语法的替代方法仍然适用于控制台:
% NAME="Atmel maXTouch Digitizer"
% LINE=$(xinput | grep "$NAME")
% echo $LINE
⎜ ↳ Atmel Atmel maXTouch Digitizer id=12 [slave pointer (2)]
% PART=$(echo $LINE | grep -o "id=[0-9]+")
% echo $PART
id=12
% DEVICE=$(echo $PART | tr -d id=)
% echo Device found: $DEVICE
Device found: 12
...但不在剧本中:
% touchscreen
⎜ ↳ Atmel Atmel maXTouch Digitizer id=12 [slave pointer (2)]
Device found:
使用one-liner的相同替代语法也适用于控制台,但不适用于脚本。
我在Arch Linux上运行zsh。我使用#!/bin/zsh
和#!/bin/bash
对此进行了测试,结果相同。我很沮丧。
答案 0 :(得分:1)
如果您使用带有grep
选项的-E
来启用解释作为扩展正则表达式,则您使用的模式仅按预期工作。如果没有-E
,+
必须引用\
:`“grep -o”id = [0-9] +“。
所以使用
grep -Eo "id=[0-9]+"
应解决眼前的问题。
它在命令行上工作但不在脚本中工作的原因很可能是grep
在使用命令行时实际上是别名vor grep -E
(可能还有一些其他选项)但实际{脚本中的{1}}命令。您可以通过运行grep
来查看此内容。
虽然别名可以在脚本中使用,也可以在命令行中使用,但它们总是必须在同一个上下文中定义。这可以直接在命令行或脚本中进行,也可以在相应的配置文件中进行设置。
对于交互式shell,这通常发生在type grep
(很可能是$ZDOTDIR/.zshrc
)。但是在使用脚本时,只会读取配置文件~/.zshrc
和/etc/zshenv
(因为它们适用于任何其他zsh实例)。
如果别名仅在$ZDOTDIR/.zshenv
中定义,则脚本无法使用。
尽管如此,您实际上并不需要在此使用~/.zshrc
或grep
。 tr
可以自行完成所有操作:
xinput
即使这可能也不需要,因为在大多数情况下NAME="Atmel maXTouch Digitizer"
xinput list --id-only $NAME
##If you are not using zsh you may have to quote $NAME (it also works for zsh)
xinput list --id-only "$NAME"
可以使用设备的名称而不是id。