長い行に4文字ごとにスペースを挿入するにはどうすればよいですか?


30

読みやすいように1行の実線で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
望ましいことではないかもしれない文字列中の1つの以上の文字がある場合、これは、同様末尾にスペースを追加することに留意すべきである
アヌビス

@アヌビス'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など)では機能しません。
ステファンシャゼラス

3

grepand を使用した例を次に示しxargsます。

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

xargsechoデフォルトで実行されるため-nenecho実装によってはバックスラッシュなどの単語やバックスラッシュを含む単語では動作しません。xargsが複数実行されている場合、奇妙な改行文字も時々表示されechoます。paste -sd ' ' -代わりにパイプすることをお勧めします。-oこれは標準オプションではないことに注意してください。
ステファンシャゼラス

3

bashのみで、外部コマンドはありません:

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

または、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問題がある場合は、1つではなく2つのsを使用します。

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

最初printfは最初の4文字(最大)を印刷し、2番目はグループを区切るスペースを先頭に追加して(もしあれば)条件付きですべてを印刷します。テストは、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"

さて、それは文字です。あなたは、(例えば、破るために書記素クラスタ上でそれをやってみたかった場合はStéphane、として書かれた$'Ste\u0301phane'として、Stép haneそしてない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

必要に応じてスペースを挿入するだけで答えますので、1行に少なくとも4文字ごとにスペースが表示されます。このケースをどの方法で処理するかはわかりません。たとえば、「aa bbccdd」の入力を指定すると、「aa b bccd d」ではなく「aa bbcc dd」の出力が得られます。

先読みに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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.