긴 줄에 네 문자마다 공백을 어떻게 삽입합니까?


30

4 줄마다 공백을 삽입하여 한 줄짜리 단색 텍스트로 쉽게 읽을 수 있도록하기 위해 가장 긴 방법은 무엇입니까? 또한 파이프에서 라인을 입력 할 수 있어야합니다. 예 :

echo "foobarbazblargblurg" | <some command here>

준다

foob arba zbla rgbl urg

답변:


54

다음과 같이 sed를 사용하십시오.

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

1
저주 에 너무 가까이 저주sed먼저 시도 할 수 있습니다.
xenoterracide

7
궁금한 점이 있다면 '&'는 무엇입니까? 오, 그것은 '방금 일치 한 것'의 약자입니다. 바보 나.
Omnifarious

1
문자열에 하나 이상의 문자가있는 경우 끝에 공백이 추가됩니다. 바람직하지 않을 수도 있습니다.
Anubis

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

20

다음과 같은 간단한 예를 사용할 수 있습니다.

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

아주 좋은 ... 나는 이것이 sed대답 보다 낫다고 생각합니다 . 나는 fold전에 몰랐다 .
와일드 카드

1
불행히도 현재 GNU 버전 에서는 UTF-8 fold에서 echo €€€€€€€€ | fold -w4 | paste -sd' ' -와 같이 멀티 바이트 문자와 작동하지 않습니다 .
Stéphane Chazelas

3

다음은 grepand 를 사용하는 예입니다 xargs.

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

xargsecho기본적으로 실행 되므로 구현 -nen에 따라 백 슬래시를 포함하거나 이와 유사한 단어로는 작동하지 않습니다 echo. xargs가 여러 개 실행되는 경우 홀수 줄 바꿈 문자가 가끔씩 나타납니다 echo. paste -sd ' ' -대신 파이프하는 것이 좋습니다. 참고 -o표준 옵션이 아닙니다.
Stéphane 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. 문제가 있으면 하나 대신 두 개를 사용하십시오 .

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

첫 번째 printf문자는 첫 번째 4 자까지 인쇄하고, 두 번째 문자는 조건부로 나머지 문자 (있는 경우)를 선행 공백으로 인쇄하여 그룹을 분리합니다. 테스트는 0 번째 요소를 설명하기 위해 4 개가 아닌 5 개 요소에 대한 것입니다.

노트:

  • printf'들 %c대신에 사용될 수있다 %s, %c(아마도) 의도를 명확하게하지만 멀티 바이트 문자 안전하지. bash 버전이 가능한 경우 위의 모든 바이트 문자를 안전하게 사용할 수 있습니다.
  • printf은 인자가 다 떨어질 때까지 형식 문자열을 재사용하므로 한 번에 4 개의 인자를 모으고 후미 인수를 처리합니다 (따라서 다른 대답과 달리 가장자리가 필요하지 않습니다)
  • BASH_REMATCH[0] 일치하는 전체 문자열이므로 인덱스 1에서 시작하는 출력 만
  • 사용 printf -v myvar ...변수에 저장 대신 myvar(보통 읽기 루프 / 서브 쉘의 행동에 따라)
  • printf "\n"필요한 경우 추가

대신 zsh배열을 사용하는 경우 위의 작업을 수행 하고 전체 일치와 함께 0 요소를 유지하지 않으므로 모든 인덱스에서 1을 뺍니다 .match[]BASH_REMATCH[]zsh


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 쉘만 사용 (입력 길이가 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"

자, 그것은 characters 입니다. grapheme 클러스터에서 수행하려면 (예 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수도 있습니다.이 경우 위와 같이 작동 하지만 다른 종류의 0 너비 또는 2 너비 문자가 관련된 경우에도 도움이 될 수 있습니다.

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 b bccd d"대신 "aa bbcc dd"가 출력됩니다.

나는 Pera를 lookahead에 사용하고 있지만, 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

파이썬을 사용 하여이 작업을 수행했습니다.

먼저 파일을 읽은 다음 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.