【问题标题】:Adding spaces after each character in a string在字符串中的每个字符后添加空格
【发布时间】:2014-04-17 06:54:01
【问题描述】:

我的脚本中有一个字符串变量,由 ls -l 的 9 个权限字符组成

例如:

rwxr-xr--

我想对其进行操作,使其显示如下:

r w x     r - x     r - -

IE 每三个字符用制表符分隔,所有其他字符用空格分隔。我最接近的是使用 printf

printf "%c %c %c\t%c %c %c\t%c %c %c\t/\n" "$output"{1..9}

这只会打印第一个字符但格式正确

我确信有一种方法可以使用我想不到的“sed”

有什么建议吗?

【问题讨论】:

  • 有什么建议吗? Don't parse ls output.stat(1) 的输出更容易以编程方式处理。
  • echo "$output"{1..9} 会告诉你你的命令哪里出错了。 . .
  • @tripleee:非常感谢您的建议!然而,这是一个任务,我们被告知要忽略你描述的奇怪情况。但是,您是绝对正确的,总的来说,我应该记住这一点。不幸的是,我在使用 ls -l 重写方面做得太过分了......我的问题仅仅是关于以我要求的方式简单地格式化一个 9 个字符的字符串
  • @ruakh:我知道它为什么不起作用......因为每次它都会重新处理变量。因此,为什么我说这是我最接近的,但我可能需要使用“sed”命令。
  • 提示:使用正则表达式匹配来填充BASH_REMATCH,每个数组元素一个字符。

标签: string bash sed scripting formatting


【解决方案1】:
> echo "rwxr-xr--" | sed 's/\(.\{3,3\}\)/\1\t/g;s/\([^\t]\)/\1 /g;s/\s*$//g'
r w x    r - x    r - -

(显然我对sed 命令没有太多考虑。John Kugelman 的版本显然更清晰、更简洁。)

编辑:我完全同意 Triplee 的评论。不要浪费时间尝试解析ls 输出。我这样做了很长时间,然后才发现您可以通过使用更轻松地获得您想要的(并且您想要的)非常 stat。例如:

> stat -c %a foo.bar  # Equivalent to stat --format %a
0754

-c %a 告诉stat 以八进制输出指定文件的访问权限。这就是它打印出来的全部,从而消除了像ls foo.bar | awk '{print $1}' 等古怪的东西的需要。

因此,例如,您可以执行以下操作:

GROUP_READ_PERMS=040
perms=$(stat -c %a foo.bar)
if (( (perms & GROUP_READ_PERMS) != 0 )); then
  ... # Do some stuff
fi

确实比解析“rwxr-xr--”之类的字符串更有效

【讨论】:

    【解决方案2】:
    $ sed -r 's/(.)(.)(.)/\1 \2 \3\t/g' <<< "$output"
    r w x   r - x   r - -   
    

    遗憾的是,这会在输出中留下一个尾随标签。如果你不想这样,请使用:

    $ sed -r 's/(.)(.)(.)/\1 \2 \3\t/g; s/\t$//' <<< "$str"
    r w x   r - x   r - -
    

    【讨论】:

    • 为什么这让我想起了Total Recall中的一个场景?
    • @John Kugelman - 现在试试这个,但它看起来和我想要的完全一样!我确实想要一个尾随 \t 非常感谢!
    【解决方案3】:

    设置awk -F '' 允许每个字符有界,然后您需要循环并打印每个字段。

    例子:

    ls -l | sed -n 2p | awk -F '' '{for(i=1;i<=NF;i++){printf " %s ",$i;}}'; echo ""
    

    这部分似乎是您问题的答案:

    awk -F '' '{for(i=1;i<=NF;i++){printf " %s ",$i;}}'
    

    我意识到,这并没有提供您想要的三元分组。嗯……

    【讨论】:

      【解决方案4】:

      使用 Posix 指定的实用程序 foldpaste,将字符串拆分为单个字符,然后交错一系列分隔符:

      fold -w1 <<<"$str" | paste -sd'  \t'
      

      【讨论】:

      • 不确定但 POSIX 粘贴不需要用 - 声明 STDIN?
      • @jaypal 是的,但使用 -s 通常不需要。
      • 感谢@rici 的澄清! +1
      • 又名“如何打印持续集成管道机密,因为字符之间有空格的机密不会被星号替换”
      【解决方案5】:

      为什么你需要解析它们? U 可以通过复制需要的元素来访问字符串的每个元素。这是一个非常简单且没有任何实用程序的工具,例如:

      DATA="rwxr-xr--"
      
      while [ $i -lt ${#DATA} ]; do
       echo ${DATA:$i:1}
       i=$(( i+1 ))
      done
      

      【讨论】:

        【解决方案6】:

        awk:

        $ echo "rwxr-xr--" | awk '{gsub(/./,"& ");gsub(/. . . /,"&\t")}1'
        r w x   r - x   r - -
        

        【讨论】:

          【解决方案7】:
          sed 's/.../& /2g;s/./& /g' YourFile
          

          简单两步

          【讨论】:

            【解决方案8】:

            一个版本,其中包含用于短字符串的纯 bash 版本和用于较长字符串的 sed,并保留换行符(也在它们后面添加一个空格)

            if [ "${OS-}" = "Windows_NT" ]; then
              threshold=1000
            else
              threshold=100
            fi
            
            function escape()
            {
              local out=''
              local -i i=0
              local str="${1}"
              if [ "${#str}" -gt "${threshold}" ]; then
                # Faster after sed is started
                sed '# Read all lines into one buffer
                     :combine
                     $bdone
                     N
                     bcombine
                     :done
                     s/./& /g' <<< "${str}"
              else
                # Slower, but no process to load, so faster for short strings. On windows
                # this can be a big deal
                while (( i < ${#str} )); do
                  out+="${str:$i:1} "
                  i+=1
                done
                echo "$out"
              fi
            }
            

            sed 的解释。 “如果这是最后一行,跳转到:done,否则将Next追加到缓冲区并跳转到:combine:done之后是一个简单的sed替换表达式。整个字符串(换行符和所有)都在一个缓冲区中,所以替换也适用于换行符(在某些awk -F 示例中丢失了)

            Plus这与 Linux、Mac 和 Git for Windows 兼容。

            【讨论】:

              猜你喜欢
              • 2013-12-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-10-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多