web-dev-qa-db-ja.com

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

読みやすくするために、1行の実線テキストに4文字ごとにスペースを挿入したい長い行がありますが、これを行う最も簡単な方法は何ですか?また、パイプからラインを入力できるはずです。例えば.

echo "foobarbazblargblurg" | <some command here>

与える

foob arba zbla rgbl urg
34
xenoterracide

次のようにsedを使用します。

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

次の簡単な例を使用できます。

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

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の場合です。書記素クラスタでそれを実行したい場合(たとえば、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"
4

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 

カウントを簡単にパラメーター化して、フォーマット文字列を適宜調整できます。

末尾にスペースが追加されます。問題がある場合は、1つではなく2つのprintfsを使用します。

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

最初のprintfは最初の4文字を(最大で)印刷し、2番目は条件付きで残りのすべて(存在する場合)をグループで区切るための先行スペースを付けて印刷します。テストは、0番目の要素を説明するために、4ではなく5つの要素に対して行われます。

ノート:

  • シェルprintf 's%c%sの代わりに使用できます。%c(多分)は意図をより明確にしますが、マルチバイト文字の安全性はありません。 bashのバージョンが対応している場合、上記はすべてマルチバイト文字に対して安全です。
  • Shell printfは、引数がなくなるまでフォーマット文字列を再利用するため、一度に4つの引数を取得し、最後の引数を処理します(したがって、ここにある他のいくつかの回答とは異なり、Edgeのケースは必要ありません。間違いなく)
  • BASH_REMATCH[0]は一致した文字列全体であるため、インデックス1から始まる出力のみ
  • 代わりにprintf -v myvar ...を使用して変数myvarに格納します(通常の読み取りループ/サブシェルの動作に従う)
  • 必要に応じてprintf "\n"を追加します

match[]の代わりに配列BASH_REMATCH[]を使用し、zshが保持しないため、すべてのインデックスから1を引く場合、zshで上記を機能させることができます。完全に一致する0要素。

3
mr.spuratic

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

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

必要に応じてスペースを挿入するだけで答えるので、少なくとも行の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)
2
Fred Nurk

私は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
0