【问题标题】:BASH split variable in characters and print out space in for loopBASH 在字符中拆分变量并在 for 循环中打印出空格
【发布时间】:2013-03-30 10:28:31
【问题描述】:

我正在尝试创建一个精美的欢迎消息,以便在终端打开时显示。我用这段代码在 Java 中完成了它:

public void slowPrint() {
    String message = "Welcome, " + System.getProperty("user.name");

    try {
        for(int i = 0; i < message.length(); i++) {
            System.out.print(message.charAt(i));
            Thread.sleep(50);
        }
    } catch(InterruptedException ex) {
        ex.printStackTrace();
    }
}

现在,我对 bash 还很陌生,但我已经设法编写了这段代码:

for i in W e l c o m e , $USER; do
    echo -ne $i
    sleep 0.05
done

echo !

这段代码有两个问题:

  1. 我不知道如何在逗号后面打印一个纯空格,输出只是Welcome,simon! 我怎样才能让它输出一个空格呢?
  2. 当然,它会将$USER 打印为一个完整的单词。我希望它是一个字符一个字符,我该怎么做?

【问题讨论】:

    标签: bash loops for-loop space


    【解决方案1】:

    你可以使用标准的 for 循环来达到同样的效果:

    MESSAGE="Welcome, $USER"
    for (( i=0; i<${#MESSAGE}; i++ )); do
        echo -ne "${MESSAGE:$i:1}"
        sleep 0.05
    done
    echo !
    

    ${MESSAGE:$i:1} 语法从字符串中的位置 i 获取一个子字符串 1。将该部分括在引号中可确保同时打印空格和制表符之类的内容。

    【讨论】:

    • 你忘记了引号,所以空格没有打印出来。
    • 如果MESSAGE="...!" 中的! 引发event not found 错误,您可以像这样分配字符串:MESSAGE="Welcome, $USER"'!'
    【解决方案2】:

    你可以很容易地指定空间;用引号括起来:

    for i in W e l c o m e , ' ' ...
    

    可以通过多种方式将$USER 拆分为单独的字符。我这样做的方式是老式但可靠的:

    for i in W e l c o m e , ' ' $(sed 's/./& /g' <<< "$USER")
    

    注意&lt;&lt;&lt;操作保存了一个进程和一个管道;它重定向sed 的标准输入,因此它将给定的字符串作为输入行读取。

    或者,如果您认为用户名可能包含任何空格或其他特殊字符:

    for i in W e l c o m e , ' ' $(sed "s/./'&' /g" <<< "$USER")
    

    (这不是防弹的;USER="Tam O'Shanter" 的值会引起一些悲伤,而使用 USER='Will "O'\''Wisp" Light' 的简单解决方法会遇到麻烦。...咕哝,咕哝,奥术咒语,...

        for i in W e l c o m e , ' ' $(sed "s/./'&' /g; s/'''/\\\\'/g" <<< "$USER")
    

    除了在所有内容中都用单引号呼应名称;发牢骚,发牢骚,...我想我刚刚弄清楚了为什么我不会同时这样做,...空格也会妨碍...我会使用简单的第一个版本并告诉人们不要在$USER 的值中使用空格或特殊字符。)

    可能有 种方法可以做到这一点,而无需调用单独的进程,例如sed;参见heuristicusanswer。所以,就这样吧。但请注意,它与bash 紧密相关,而这个答案并不完全与bash 相关——您可以轻松地将&lt;&lt;&lt; 表示法(仅bash)替换为echo "$USER" | ... .

    【讨论】:

    • 为什么不用"$USER" 而不是$USER
    • 懒惰/疏忽;并且期望很少有用户名包含两个或多个需要保留的连续空格。
    • 但是,如果 bash 初学者在其他地方应用这种模式,这可能是一个不好的例子。
    【解决方案3】:

    完全 POSIXly 可移植,即没有那些讨厌的 bashism,也没有用于 sed 的 fork:

    #!/bin/sh
    
    m="Welcome, $USER!"
    while test ${#m} -gt 0; do
      r=${m#?}
      printf '%s ' "${m%%$r}"
      m=$r
      sleep 0.05
    done
    printf '\n'
    

    请注意,几分之一秒的睡眠是不可移植的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 2020-04-21
      • 1970-01-01
      • 2012-10-23
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      相关资源
      最近更新 更多