【问题标题】:How to get first character of variable如何获取变量的第一个字符
【发布时间】:2013-07-17 10:08:57
【问题描述】:

我正在尝试获取变量的第一个字符,但我遇到了错误替换错误。谁能帮我修一下?

代码是:

while IFS=$'\n' read line
do
  if [ ! ${line:0:1} == "#"] # Error on this line
  then
    eval echo "$line"
    eval createSymlink $line
  fi
done < /some/file.txt

我做错了什么还是有更好的方法?

-- 编辑--

根据要求 - 这是存储在 /some/file.txt 中的一些示例输入

$MOZ_HOME/mobile/android/chrome/content/browser.js
$MOZ_HOME/mobile/android/locales/en-US/chrome/browser.properties
$MOZ_HOME/mobile/android/components/ContentPermissionPrompt.js

【问题讨论】:

  • 也许你需要在右引号和右括号之间留一个空格,即"#" ]
  • 你也可以选择A != B而不是! A == B
  • @doubleDown 这些都不起作用 - 对不起!该行仍然出现错误替换错误
  • @Martyn 你可以从 file.txt 中发布一些输入数据以便我们进行测试吗?
  • 文件中可能有空行,或者以空格开头的行?试试if [ ! "${line:0:1}" == "#" ]

标签: bash


【解决方案1】:

要获取变量的第一个字符,您需要说:

v="hello"
$ echo "${v:0:1}"
h

但是,您的代码有语法错误:

[ ! ${line:0:1} == "#"]
#                     ^-- missing space

所以这可以解决问题:

$ a="123456"
$ [ ! "${a:0:1}" == "#" ] && echo "doesnt start with #"
doesnt start with #
$ a="#123456"
$ [ ! "${a:0:1}" == "#" ] && echo "doesnt start with #"
$ 

也可以这样:

$ a="#123456"
$ [ "$(expr substr $a 1 1)" != "#" ] && echo "does not start with #"
$ 
$ a="123456"
$ [ "$(expr substr $a 1 1)" != "#" ] && echo "does not start with #"
does not start with #

更新

根据您的更新,这对我有用:

while IFS=$'\n' read line
do
  echo $line
  if [ ! "${line:0:1}" == "#" ] # Error on this line
  then
    eval echo "$line"
    eval createSymlink $line
  fi
done < file

【讨论】:

  • 现在我看到 doubleDown 评论了它。当他发布他的答案时将删除!
  • 我也会给你一个体育精神+1!仅供参考,我试过这个:a="123456" | [ ! "${a:0:1}" == "#" ] && echo "doesnt start with #" 并且也出现了 BS 错误。会不会和 bash 版本有关?
  • 哦,我明白了,嗯。 [ "${a:0:1}" != "#" ] 呢?也许是 ` [ ! a == b ]` 不适合您的 bash 版本。
  • 很高兴看到这一点,@Martyn!您可以在tldp.org/LDP/abs/html/refcards.html 中获得更多信息
  • 如果@doubleDown 想发布答案,我会遵守删除我的承诺:D +3 票甚至会让我获得纪律严明的徽章!
【解决方案2】:

试试这个:

while IFS=$'\n' read line
do
  if ! [ "${line:0:1}" = "#" ]; then
    eval echo "$line"
    eval createSymlink $line
  fi
done < /some/file.txt

或者您可以将以下内容用于您的 if 语法:

if [[ ! ${line:0:1} == "#" ]]; then

【讨论】:

  • +1 将否定条件放在括号之外也很好。我想知道最 POSIX 的方式是什么!
  • @fedorqui:'!'是 test ([) 命令的有效“非”参数,所以我自己把它放在里面
【解决方案3】:

添加缺少的空格(如fedorqui's answer 中所建议的那样;))对我有用。

另一种方法/语法

如果我想检查字符串的第一个字符,我会在 Bash 中执行以下操作

if [[ $line != "#"* ]]

== 的右侧,引用的部分按字面意思处理,而* 是任何字符序列的通配符。

更多信息,请参见 Bash 参考手册Conditional Constructs 的最后部分:

当使用‘==’和‘!=’操作符时,操作符右边的字符串被认为是一个模式,并根据下面Pattern Matching中描述的规则进行匹配

检查您是否使用了正确的 shell

如果您收到诸如“错误替换错误”和“[[: not found”之类的错误(请参阅comment),即使您的语法没问题(并且对其他人工作正常),这可能表明您使用了错误的 shell(即不是 Bash)。

所以要确保您使用 Bash 来运行脚本,或者

  • 使脚本可执行并使用适当的 shebang,例如#!/bin/bash
  • 或通过bash my_script执行

另外请注意,sh 不一定是 bash,有时它可以是 dash(例如在 Ubuntu 中)或只是普通的 Bourne shell .

【讨论】:

  • 也许......你甚至没有使用 Bash?
  • % echo $SHELL /bin/bash
  • type [[ 的作用是什么?
  • % type [[ [[是一个shell关键字
  • @fedorqui,是的。我很高兴这最终没有成为那些不可重现的神秘案件之一。
【解决方案4】:

TIMTOWTDI ^^

while IFS='' read -r line
do
  case "${line}" in
    "#"*)  echo "${line}"
    ;;
    *)     createSymlink ${line}
    ;;
  esac
done  < /some/file.txt

注意:我放弃了 eval,在某些(罕见!)情况下可能需要它(并且通常很危险)。

注意2:我添加了一个“更安全”的 IFS & read (-r, raw),但如果它更适合,您可以恢复为您自己的。请注意,它仍然逐行读取。

注意 3:我习惯于总是使用 ${var} 而不是 $var ... 对我有用(很容易在复杂的文本中找到 var,并且很容易随时看到它们的开始和结束位置)但是这里不需要。

注意4:您也可以将测试更改为:*"#"*),如果某些(cmets?)行在“#”之前可以有空格或制表符(并且没有任何符号链接行包含“#”)

【讨论】:

    猜你喜欢
    • 2021-04-24
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 2011-03-26
    • 2020-04-17
    相关资源
    最近更新 更多