【问题标题】:How to print character just after a particular character in a string using bash如何使用bash在字符串中的特定字符之后打印字符
【发布时间】:2018-03-16 08:38:12
【问题描述】:

我有一个类似的字符串

abc def 0/1 dls dl 9/0 1//o

我想将01(字符串中第一个/ 之后和之前的字符)转换为两个变量,比如$NUM1$NUM2,并对它们进行一些进一步的逻辑处理.

【问题讨论】:

  • 看一下参数扩展运算符:gnu.org/software/bash/manual/html_node/…
  • SO 不是免费的编码服务。您必须自己尝试解决问题。如果您无法使其正常工作,请发布您尝试过的内容,我们会帮助您解决问题。
  • 我认为 stackoverflow 的另一个用途是帮助其他人更快地解决相同的一般问题。我相信所有的问题都是为了解决。引用每个人都必须站在巨人的肩膀上才能看得更远
  • 不,这不是应该使用 SO 的方式。阅读帮助页面。
  • 但是我看到很多类似的问题,所以问了。

标签: regex bash shell scripting


【解决方案1】:

您可以使用 sed 来解析带有正则表达式的行以提取数字:

NUM1=$(echo 'abc def 0/1 dls dl 9/0 1//o' | sed 's@[^0-9]*\([0-9]*\)/[0-9]*.*@\1@')
NUM2=$(echo 'abc def 0/1 dls dl 9/0 1//o' | sed 's@[^0-9]*[0-9]*/\([0-9]*\).*@\1@')
echo $NUM1
0
echo $NUM2
1

【讨论】:

    【解决方案2】:

    我假设您是基于空格隐式分隔字符。所以你想要从空格到第一个'/'的字符,从第一个'/'到下一个空格。我可能会使用 sed:

    echo "abc def 0/1 dls dl 9/0 1//o" | sed -r 's%^[^/]* ([^ ]*)/([^ ]*) .*%\1 \2%'
    

    但请注意,如果第一个“/”之前没有空格,这将不起作用。对于这种情况,您可能希望有另一种模式。

    【讨论】:

      【解决方案3】:

      只使用shell parameter expansion:

      $ str='abc def 0/1 dls dl 9/0 1//o'
      $ num1=${str%%/*}    # Remove first "/" and everything after it
      $ echo "$num1"
      abc def 0
      $ num1=${num1##* }   # Remove last space and everything before it
      $ echo "$num1"
      0
      $ num2=${str#*/}     # Remove first "/" and everything before it
      $ echo "$num2"
      1 dls dl 9/0 1//o
      $ num2=${num2%% *}   # Remove first space and everything after it
      $ echo "$num2"
      1
      

      ###%%% 在这里必须小心使用。单次重复去掉后面模式的最短匹配,重复使用去掉最长的匹配。


      或者,在第一次扩展之后,您只需要字符串的第一个或最后一个字符,这可以通过子字符串扩展来解决:

      $ echo "$num1"
      abc def 0
      $ echo "${num1:(-1)}"  # Extract last character
      0
      $ echo "$num2"
      1 dls dl 9/0 1//o
      $ echo "${num2:0:1}"   # Extract first character
      1
      

      负索引至少需要 Bash 4.2。对于较旧的 Bash 版本,我们可以使用

      echo "${num1:${#num1}-1}"
      

      最后,我们可以使用 Bash 正则表达式,如 glenn jackman's answer 所示。

      【讨论】:

      • 是的,不擅长正则表达式,我发现你的答案最容易理解。再次感谢
      • @ParantapSharma 请注意,这些不是正则表达式:它们是 shell 模式(或“globs”)。
      • 也可以使用子字符串:num1=${str%%/*}; echo ${num:(-1):1}; num2=${str#*/}; echo ${num2:0:1}
      • 对不起,不知道他们的术语
      • @glennjackman 没错,我在心理上假设应该捕获下一个空格 / 之间的所有字符,但事实并非如此。
      【解决方案4】:

      您可以使用 bash 正则表达式,它使用捕获的子表达式填充 BASH_REMATCH 数组:

      if [[ $a =~ (.)/(.) ]]; then
        num1=${BASH_REMATCH[1]}
        num2=${BASH_REMATCH[2]}
      fi
      echo $num1 $num2
      
      0 1
      

      不要养成使用 ALL_CAPS_VARNAMES 的习惯:有一天你会不小心写了PATH=/my/path,然后想知道为什么你的脚本坏了。为 shell 和操作系统保留大写变量

      【讨论】:

      • 感谢您的回答,也感谢您对变量命名的宝贵建议。从现在开始将在我的脚本中遵循这一点。
      • 不,我认为即使对于非脚本编写者来说也很容易阅读。我认为的第一种方法实际上是迭代直到我看到 / 并将位置存储在 var 中,然后截断直到那里。我知道那会非常低效,因此寻求建议。再次感谢。
      猜你喜欢
      • 2015-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-30
      相关资源
      最近更新 更多