Shell 脚本 Bash,检查字符串是否以单引号开头和结尾

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40317552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:21:03  来源:igfitidea点击:

Shell script Bash, Check if string starts and ends with single quotes

bashshell

提问by chichi

I need to check if a string starts and ends with a single quote, for example 'My name is Mozart'

我需要检查字符串是否以单引号开头和结尾,例如“我的名字是莫扎特”

What I have is this, which doesn't work

我有的是这个,这不起作用

if [[ $TEXT == '*' ]] ;

This does not work either

这也不起作用

if [[ $TEXT == /'*/' ]] ;

But if I change it to

但是如果我把它改成

if [[ $TEXT == a*a ]] ;

it works for a sentence like 'an amazing apa'. So I Believe it has to do with the single quote sign.

它适用于像“一个惊人的 apa”这样的句子。所以我相信它与单引号有关。

Any ideas on how I can solve it?

关于如何解决它的任何想法?

回答by Cyrus

With a regex:

使用正则表达式

if [[ $TEXT =~ ^\'.*\'$ ]]

With globbing:

使用通配符

if [[ $TEXT == \'*\' ]]

回答by Sulav Timsina

I am writing the complete bash script so you won't have any confusion:

我正在编写完整的 bash 脚本,所以您不会有任何困惑:

#! /bin/bash
text1="'helo there"
if [[ $text1 =~ ^\'.*\'$ ]]; then
        echo "text1 match"
else
        echo "text1 not match"

fi

text2="'hello babe'"
if [[ $text2 =~ ^\'.*\'$ ]]; then
        echo "text2 match"
else
        echo "text2 not match"
fi

Save the above script as matchCode.sh

将上面的脚本另存为 matchCode.sh

Now run it as: ./matchCode

现在运行它: ./matchCode

output:

输出:

text1 not match
text2 match

Ask if you have any confusion.

问你是否有任何困惑。

回答by mklement0

Cyrus' helpful answersolves your problem as posted.

赛勒斯的有用回答解决了您发布的问题。

However, I suspect you may be confused over quotes that are part of the shell syntaxvs. quotes that are actually part of the string:

但是,我怀疑您可能对作为 shell 语法一部分的引号与实际上是字符串一部分的引号感到困惑

  • In a POSIX-like shell such as Bash, 'My name is Mozart'is a single-quoted string whose content is the literal My name is Mozart- withoutthe enclosing '. That is, the enclosing 'characters are a syntactic elementsthat tell the shell that everything betweenthem is the literal contentsof the string.

  • By contrast, to create a string whose contentis actually enclosed in '- i.e., has embedded'instances, you'd have to use something like: "'My name is Mozart'". Now it is the enclosing "instances that are the syntactic elements that bookend the string content.

    • Note, however, that using a "..."string (double quotes) makes the contents subject to string interpolation(expansion of embedded variable references, arithmetic and command substitutions; none in the case at hand, however), so it's important to know when to use '...'(literal strings) vs. "..."(interpolated strings).
    • Embedding 'instances in '...'strings is actually not supported at all in POSIX-like shells, but in Bash, Ksh, and Zsh there's another string type that allows you to do that: ANSI C-quoted strings, $'...', in which you can embed 'escaped as \': $'\'My name is Mozart\''
    • Another option is to use string concatenation: In POSIX-like shells, you can place substrings employing different quoting styles (including unquoted tokens) directlynext to one another in order to form a single string: "'"'My Name is Mozart'"'"would also give you a string with contents'My Name is Mozart'.
      POSIX-like shells also allow you to escape individual, unquoted characters(meaning: neither part of a single- nor a double-quoted string) with \; therefore, \''My name is Mozart'\'yields the same result.
  • 在类似 POSIX 的 shell 中,例如 Bash,'My name is Mozart'是一个单引号字符串,其内容是文字My name is Mozart——没有封闭的'. 也就是说,封闭 '字符是一个句法元素,它告诉外壳它们之间的所有内容都是字符串的文字内容

  • 相比之下,创建一个字符串,其内容实际上是封闭的'-即已经嵌入的'情况下,你必须使用这样的:"'My name is Mozart'"。现在它是包含"字符串内容的语法元素的封闭实例。

    • 但是请注意,使用"..."字符串(双引号)会使内容受到字符串插值的影响(嵌入变量引用的扩展、算术和命令替换;但是在手头的情况下没有),因此知道何时使用'...'(文字字符串)与"..."(内插字符串)。
    • ''...'类似 POSIX 的 shell 中实际上根本不支持在字符串中嵌入实例,但是在 Bash、Ksh 和 Zsh 中,还有另一种字符串类型允许您这样做:ANSI C 引用的字符串, $'...',您可以在其中嵌入'转义为\'$'\'My name is Mozart\''
    • 另一种选择是使用字符串连接:在类似 POSIX 的 shell 中,您可以将采用不同引用样式(包括未加引号的标记)的子字符串直接放在一起,以形成单个字符串:"'"'My Name is Mozart'"'"也会为您提供一个包含内容的字符串'My Name is Mozart'
      类似 POSIX 的 shell 还允许您使用 ; 转义单个未加引号的字符(意思是:既不是单引号字符串的一部分,也不是双引号字符串的一部分)\。因此,\''My name is Mozart'\'产生相同的结果。


The behavior of Bash's ==operator inside [[ ... ]](conditionals)may have added to the confusion:

Bash==操作符内部[[ ... ]](条件)行为可能增加了混乱:

If the RHS (right-hand side - the operand to the right of operator ==) is quoted, Bash treats it like a literal; only unquotedstrings (or variable references) are treated as (glob-like) patterns:

如果引用了 RHS(右侧 - operator 右侧的操作数==),Bash 会将其视为文字;只有未加引号的字符串(或变量引用)被视为(类似全局的)模式

'*'matches literal*, whereas *(unquoted!) matches any sequence of characters, including none.

'*'匹配文字*,而*(未加引号!)匹配任何字符序列,包括无。

Thus:

因此:

  • [[ $TEXT == '*' ]]would only ever match the single, literal character *.

  • [[ $TEXT == /'*/' ]], because it mistakes /for the escape character - which in reality is \- would only match literal/*/(/'*/'is effectively a concatenation of unquoted /and single-quoted literal */).

  • [[ $TEXT == a*a ]], due to using an unquotedRHS, is the only variant that actually performs pattern matching: any string that starts with aand ends with ais matched, including aa(because unquoted *represents any sequence of characters).

  • [[ $TEXT == '*' ]]只会匹配单个文字字符*

  • [[ $TEXT == /'*/' ]],因为它误/认为转义字符 - 实际上是\- 只会匹配文字/*//'*/'实际上是未引用/和单引号文字的串联*/)。

  • [[ $TEXT == a*a ]],由于使用了未加引号的RHS,它是实际执行模式匹配的唯一变体:任何以 开头a和结尾的字符串都a被匹配,包括aa(因为未加引号*表示任何字符序列)。



To verify that Cyrus' commands do work with strings whose contentis enclosed in (embedded) single quotes, try these commands, which - on Bash, Ksh, and Zsh - should both output yes.

要验证 Cyrus 的命令是否适用于内容包含在(嵌入的)单引号中的字符串,请尝试这些命令,它们在 Bash、Ksh 和 Zsh 上都应该输出yes.

[[ "'ab'" == \'*\' ]] && echo yes  # pattern matching, indiv. escaped ' chars.

[[ "'ab'" =~ ^\'.*\'$ ]] && echo yes # regex operator =~