Shell代码在控制台中工作,但不在脚本中

时间:2015-01-19 09:15:24

标签: linux bash shell zsh

我有一些简单的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对此进行了测试,结果相同。我很沮丧。

1 个答案:

答案 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中定义,则脚本无法使用。


尽管如此,您实际上并不需要在此使用~/.zshrcgreptr可以自行完成所有操作:

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。