如何在长行中每四个字符插入一个空格?

如何在长行中每四个字符插入一个空格?

我有很长的一行,我想在纯文本的单行上每 4 个字符插入一个空格,以使其更易于阅读,最简单的方法是什么?我也应该能够从管道输入线路。例如

echo "foobarbazblargblurg" | <some command here>

给出

foob arba zbla rgbl urg

答案1

使用 sed 如下:

$ echo "foobarbazblargblurg" | sed 's/.\{4\}/& /g'
foob arba zbla rgbl urg

答案2

您可以使用以下简单示例:

$ echo "foobarbazblargblurg" | fold -w4 | paste -sd' ' -
foob arba zbla rgbl

答案3

仅在 bash 中,无外部命令:

str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"

或者作为单行管道版本:

echo foobarbazblargblurg | 
  { IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
    printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }

其工作方式是将字符串的每个字符转换为“(.)”以进行正则表达式匹配并使用 进行捕获=~,然后从数组中输出捕获的表达式 BASH_REMATCH[],并根据需要进行分组。保留前导/尾随/中间空格,删除周围的引号"${BASH_REMATCH[@]:1}"以省略它们。

这里它被包装在一个函数中,这个函数将处理它的参数,或者如果没有参数则读取 stdin:

function fmt4() {
  while IFS= read -r str; do
    [[ $str =~ ${str//?/(.)} ]]
    printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
  done < <( (( $# )) && printf '%s\n' "$@" || printf '%s\n' $(< /dev/stdin) )
}

$ echo foobarbazblargblurg | fmt4
foob arba zbla rgbl urg 

您可以轻松参数化计数以相应地调整格式字符串。

添加尾随空格,printf如果有问题,请使用两个而不是一个:

printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"

第一个printf打印(最多)前 4 个字符,第二个有条件地打印所有其余字符(如果有),并用前导空格分隔各组。该测试针对 5 个元素而不是 4 个元素来说明第 0 个元素。

笔记:

  • shellprintf可以%c用来代替%s, %c(也许)使意图更清晰,但它不是多字节字符安全的。如果您的 bash 版本支持,则以上内容都是多字节字符安全的。
  • shellprintf重用其格式字符串,直到用完参数,因此它一次只会吞噬 4 个参数,并处理尾随参数(因此不需要边缘情况,不像这里的其他一些答案,这些答案可能是错误的)
  • BASH_REMATCH[0]是整个匹配的字符串,所以只输出从索引1开始的
  • 使用printf -v myvar ...而不是存储到变量myvar(受通常的读取循环/子shell行为的影响)
  • printf "\n"如果需要的话添加

zsh如果您使用数组match[]而不是,则可以使上述工作正常进行BASH_REMATCH[],并从所有索引中减去 1,因为zsh不会在整个匹配中保留 0 元素。

答案4

grep这是使用和 的示例xargs

$ echo "foobarbazblargblurg" | grep -o .... | xargs
foob arba zbla rgbl

相关内容