Bash删除正斜杠

时间:2016-09-22 18:36:07

标签: bash macos

在我的bash脚本中,我有一个变量:

c

我想创建一个包含以下内容的字符串:

appPath="/Payload/coolApp.app"

我想我可以使用bash字符串替换运算符:

"build/ios/coolApp/"

不幸的是,我发现它并没有删除子字符串中的正斜杠。

示例脚本:

${string/substring/replacement}

我的输出变为:

appPath="/Payload/coolApp.app"

appName=${appPath/"/.app"/}
appName=${appPath/"/Payload"/}

echo "build/ios/$appName/"

我的问题:为什么不删除转发斜杠? 注意:我目前正在MacOSX 10.11.6上运行

测试解决方案脚本:

build/ios//Payload/coolApp.app/

输出:

#!/bin/sh

appPath="/Payload/coolApp.app"

appName=${appPath/"/.app"/}
appName=${appPath/"/Payload"/}
echo "Original:" "build/ios/$appName/"


appName=${appPath/"\/.app"/}
appName=${appPath/"\/Payload"/}
echo "Escape \:" "build/ios/$appName/"


v1="${appPath/\/Payload/build\ios}"
echo "heemayl:" $v1


v2="${appPath##/Payload/}"
v2="build/ios/${appPath%.app}/"
echo "redneb:" $v2

6 个答案:

答案 0 :(得分:2)

您需要使用/

在字符串中转义\
$ appPath="/Payload/coolApp.app"

$ echo "${appPath/\/Payload/build\/ios}"
build/ios/coolApp.app

答案 1 :(得分:2)

使用BASH_REMATCH可以为这种情况派上用场:

appPath="/Payload/coolApp.app"
pattern='/.*/(.*)[.].*'

[[ $appPath =~ $pattern ]] && echo "build/ios/${BASH_REMATCH[1]}/"

<强>输出:

build/ios/coolApp/

双括号语句[[ $appPath =~ $pattern ]]充当IF语句,它基本上会问自己“$appPath是否适合$pattern?” - 如果确实如此,则回应替换。

以下是正则表达式模式的概要:

  

/.*/匹配/Payload/

  / matches the character / literally
  .* matches any character (except newline)
   |_ Quantifier: * Between zero and unlimited times
    / matches the character / literally
  

(.*)匹配coolApp并将其捕获到BASH_REMATCH[1]捕获组1

  1st Capturing group (.*)
  .* matches any character (except newline)
   |_ Quantifier: * Between zero and unlimited times
  

[.].*.app和其他任何内容匹配到行尾

  [.] match a single character ( character class )
   |_ . the literal character .
      .* matches any character (except newline)
       |_ Quantifier: * Between zero and unlimited times

这可能看起来很复杂,虽然一旦你理解了模式的作用,它就开始变得有意义了。能够在regex editor内可视化模式通常也有助于学习。

答案 2 :(得分:1)

  

我想我可以使用bash字符串替换运算符:

${string/substring/replacement}
     

不幸的是我发现它并没有删除正斜杠   在子串内。

但当然它确实如此,或者至少可以做到。您只需将区分替换语法的斜杠与属于数据的斜杠区分开来:

appPath=/Payload/coolApp.app

echo ${appPath/\/Payload/build/ios}

特别注意,只有第一个斜杠或双斜杠和第二个斜杠对替换语法很重要。任何后续斜杠,例如&#34; build&#34;之间的斜杠。和&#34; ios&#34;在示例中,只是数据。

此外,你的报价有点绊倒了。此表单也会输出您想要的内容:

echo ${appPath/\/Payload/build\/ios}

但这不会:

echo "${appPath/\/Payload/build\/ios}"

那是因为替换中的第二个反斜杠也只是数据,因此替换产生build/ios\/coolApp/。当出现之外的双引号时,反斜杠将被视为在后续报价删除步骤中要删除的引号字符。当它出现在里面的双引号时,它本身就是一个引号字符,只有当后面跟一个需要在该上下文中转义的字符时$,`,"或{{ 1}}),或换行。因此,在您的情况下,它只是数据,因此在命令行扩展的报价删除阶段不会删除它。

更一般地说,您在许多不需要的地方使用引号。与许多语言不同,shell语言不依赖于引号来区分字符串与其他语法元素。事实上,它在这方面几乎没有区别。您只需要使用引号来抑制一个或多个字符的特殊含义。

答案 3 :(得分:1)

有几种方法可以让替换工作:

a='/Payload/coolApp.app'

echo "simple: ${a///Payload/build/ios}"
echo "plain : ${a//'/Payload'/build/ios}"
echo "front : ${a/#'/Payload'/build/ios}"
echo "end   : build/ios/${a##*/}"

执行时会打印:

simple: build/ios/coolApp.app
plain : build/ios/coolApp.app
front : build/ios/coolApp.app
end   : build/ios/coolApp.app

简单选项只需提供与参数扩展需要一样多的/ 但这很令人困惑。

普通选项几乎相同,但引用了模式,这使得它更具可读性。

前面的选项使用#(字符串的前面)来结束/的需要。

结束选项不是替代选项,而是&#34;删除匹配的前缀模式&#34;。
它删除了截至上一个/的所有内容。然后,所需的文本被添加到前面。

但更有用的方法是使用变量:

a='/Payload/coolApp.app'

b='/Payload/'
c='build/ios/'

a=${a/"$b"/$c}"
echo "var   : ${a}"

将打印:

var   : build/ios/coolApp.app

使用变量进行重复更改:

b='/Payload/' c='build/ios/'
a=${a/"$b"/$c}
echo "var1  : ${a}"

b='.app' c='/'
a=${a/"$b"/$c}
echo "var2  : ${a}"

将打印:

var1  : build/ios/coolApp.app
var2  : build/ios/coolApp/

答案 4 :(得分:0)

试试这个:

appPath="/Payload/coolApp.app"
appPath="${appPath##/Payload/}"
appPath="build/ios/${appPath%.app}/"
echo "$appPath"

打印:

build/ios/coolApp/

答案 5 :(得分:0)

如果您只想要应用名称,请使用

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Enter a number and click enter, continue doing this process ");
        Console.WriteLine("When you finish, just click enter without giving any input");
        int i = 0;
        int[] numbersArray;
        List<int> numbersList = new List<int>();

        while (true)
        {
            String numInput = Console.ReadLine();
            numbersList.Add(Int32.Parse(numInput));
            numbersArray = numbersList.ToArray();
            if (i >= 1)
            {
                if (numbersArray[i] < numbersArray[i - 1])
                {
                    Console.WriteLine("Your series is not going up!");
                    break;
                    Environment.Exit(0);
                }

                if (numbersArray[i] > numbersArray[i - 1])
                {
                    if (numInput == "") { 
                        break;
                    }
                }
            }
            i++;
        }
            Console.WriteLine("You entered this series: ");
            for (int j = 0; j < numbersArray.Length; j++)
            { 
                Console.WriteLine(" " + numbersArray[j]);
            }
            Console.WriteLine("The length of the series youve entered is: " + numbersArray.Length);


    }
}