Shell 代码在控制台中有效,但在脚本中无效
Shell code works in console, but not in script
我有一些简单的 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:
与单行代码相同的替代语法也适用于控制台,但不适用于脚本。
我是 运行 Arch Linux 上的 zsh。我已经用 #!/bin/zsh
和 #!/bin/bash
进行了测试,结果相同。我很困惑。
如果您将 grep
与选项 -E
一起使用以启用作为扩展正则表达式的解释,则您正在使用的模式将按预期工作。如果没有 -E
,+
必须用 \
引用:`"grep -o "id=[0-9]+".
所以使用
grep -Eo "id=[0-9]+"
应该可以解决眼前的问题。
它在命令行上工作但在脚本中不起作用的原因很可能是 grep
实际上是使用命令行时 grep -E
(可能还有其他一些选项)的别名,但脚本中的实际 grep
命令。您可以通过 运行 type grep
.
检查
虽然别名既可以在脚本中使用,也可以在命令行中使用,但它们始终必须在相同的上下文中定义。这可以直接在命令行或脚本中发生,也可以通过在适当的配置文件中进行设置来发生。
对于交互式 shell,这通常发生在 $ZDOTDIR/.zshrc
(很可能是 ~/.zshrc
)。但是当使用脚本时,只有配置文件 /etc/zshenv
和 $ZDOTDIR/.zshenv
被读取(因为它们对于任何其他 zsh 实例都是如此)。
如果别名仅在 ~/.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"
甚至可能不需要,因为 xinput
在大多数情况下可以使用设备名称而不是 id。
我有一些简单的 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:
与单行代码相同的替代语法也适用于控制台,但不适用于脚本。
我是 运行 Arch Linux 上的 zsh。我已经用 #!/bin/zsh
和 #!/bin/bash
进行了测试,结果相同。我很困惑。
如果您将 grep
与选项 -E
一起使用以启用作为扩展正则表达式的解释,则您正在使用的模式将按预期工作。如果没有 -E
,+
必须用 \
引用:`"grep -o "id=[0-9]+".
所以使用
grep -Eo "id=[0-9]+"
应该可以解决眼前的问题。
它在命令行上工作但在脚本中不起作用的原因很可能是 grep
实际上是使用命令行时 grep -E
(可能还有其他一些选项)的别名,但脚本中的实际 grep
命令。您可以通过 运行 type grep
.
虽然别名既可以在脚本中使用,也可以在命令行中使用,但它们始终必须在相同的上下文中定义。这可以直接在命令行或脚本中发生,也可以通过在适当的配置文件中进行设置来发生。
对于交互式 shell,这通常发生在 $ZDOTDIR/.zshrc
(很可能是 ~/.zshrc
)。但是当使用脚本时,只有配置文件 /etc/zshenv
和 $ZDOTDIR/.zshenv
被读取(因为它们对于任何其他 zsh 实例都是如此)。
如果别名仅在 ~/.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"
甚至可能不需要,因为 xinput
在大多数情况下可以使用设备名称而不是 id。