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


30

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

echo "foobarbazblargblurg" | <some command here>

foob arba zbla rgbl urg

Answers:


54

如下使用sed:

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

1
诅咒是如此接近sed我首先尝试的自己可以踢自己。
xenoterracide 2011年

7
只是好奇,“&”的成就是什么?哦,这是“刚刚匹配的东西”的代表。傻我
2012年

1
应当注意,如果字符串中还有一个字符,这也会在末尾添加一个空格,这可能不是所希望的
Anubis

@Anubis's/.\{4\}/& /g;s/ $//'
wieczorek1990

20

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

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

很好...我认为这比sed答案还要好。我不知道fold之前。
通配符

1
不幸的是,在当前版本的GNU中fold,它不适用于多字节字符(如echo €€€€€€€€ | fold -w4 | paste -sd' ' -UTF-8中所示)。
斯特凡Chazelas

3

这是使用grep和的示例xargs

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

xargsecho默认情况下运行,因此-nen根据echo实现的不同,它不能与类似或包含反斜杠的单词一起使用。如果xargs运行不止一个,您也会偶尔看到奇怪的换行符echo。最好用管道paste -sd ' ' -代替。请注意,这-o不是标准选项。
斯特凡Chazelas

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如果有问题,请使用2 而不是1:

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

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

笔记:

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

您可以在上面工作zsh,如果你使用数组match[]来代替BASH_REMATCH[],并从所有索引减1为zsh不保持0元素与整场比赛。


3

zsh只:

str=foobarbazblargblurg

set -o extendedglob
printf '%s\n' ${str//(#m)????/$MATCH }

要么

printf '%s%s%s%s ' ${(s::)str}

ksh93只:

printf '%s\n' "${str//????/\0 }"

仅对于任何POSIX shell(如果输入长度是4的倍数,也要避免尾随空格):

out=
while true; do
  case $str in
    (?????*)
      new_str=${str#????}
      out=$out${str%"$new_str"}' '
      str=$new_str
      ;;
    (*)
      out=$out$str
      break
  esac
done
printf '%s\n' "$out"

现在,这是针对角色的。如果要在字素簇上执行此操作(例如,break Stéphane,写为$'Ste\u0301phane',as Stép hane和not Ste phan e),请使用zsh

set -o rematchpcre
str=$'Ste\u301phane' out=
while [[ $str =~ '(\X{4})(.+)' ]] {
  out+="$match[1] " str=$match[2]
}
out+=$str
printf '%s\n' $out

使用ksh93时,您也可以按显示宽度来中断显示,这适用于Stéphane上面的显示宽度,但是当涉及其他类型的零宽度或全角字符时,也可以提供帮助:

str=$'Ste\u301phane' out=
while
  start=${ printf %L.4s. "$str"; }
  start=${start%.}
  [ "$start" != "$str" ]
do
  out+="$start " str=${str#"$start"}
done
out+=$str
printf '%s\n' "$out"

2

我将通过仅按要求插入空格来回答问题,这样一行上至少每4个字符之后就会出现一个空格。不确定要使用哪种方式处理此案。例如,给定输入“ aa bbccdd”,您将获得输出“ aa bbcc dd”而不是“ aa b bccd d”。

我正在使用Perl进行前瞻,但总体上我对Perl不太熟悉,因此可能需要进行一些调整:

$ echo "foobarbazblargblurg" | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
foob arba zbla rgbl urg

$ echo 'aa bbccdd' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
aa bbcc dd
# not 'aa b bccd d'!

$ echo 'some input' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
some inpu t
# not 'some  inp ut'!

$ echo $'aabb\nc cddee' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g' | 
> while read; do echo "${REPLY}x"; done
aabbx
c cdde ex
# no spaces added at the end of the first line (while loop to add to the end of
# the line and show this)

0

我已经通过使用python做到了

首先,我正在读取文件,然后将其除以4个字符并添加空格

#!/usr/bin/python
import re
b=re.compile(r'[a-z]{4}')

p=open('/root/l.txt','r')
i=p.readlines()
for j in i:
    m=re.findall(b,j)
print " " .join (m) + "  "

/root/l.txt ==>包含您在示例中给出的内容

输出

foob arba zbla rgbl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.