読みやすくするために、1行の実線テキストに4文字ごとにスペースを挿入したい長い行がありますが、これを行う最も簡単な方法は何ですか?また、パイプからラインを入力できるはずです。例えば.
echo "foobarbazblargblurg" | <some command here>
与える
foob arba zbla rgbl urg
次のようにsedを使用します。
$ echo "foobarbazblargblurg" | sed 's/.\{4\}/& /g'
foob arba zbla rgbl urg
次の簡単な例を使用できます。
$ echo "foobarbazblargblurg" | fold -w4 | paste -sd' ' -
foob arba zbla rgbl
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"
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つのprintf
sを使用します。
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のバージョンが対応している場合、上記はすべてマルチバイト文字に対して安全です。printf
は、引数がなくなるまでフォーマット文字列を再利用するため、一度に4つの引数を取得し、最後の引数を処理します(したがって、ここにある他のいくつかの回答とは異なり、Edgeのケースは必要ありません。間違いなく)BASH_REMATCH[0]
は一致した文字列全体であるため、インデックス1から始まる出力のみprintf -v myvar ...
を使用して変数myvar
に格納します(通常の読み取りループ/サブシェルの動作に従う)printf "\n"
を追加しますmatch[]
の代わりに配列BASH_REMATCH[]
を使用し、zsh
が保持しないため、すべてのインデックスから1を引く場合、zsh
で上記を機能させることができます。完全に一致する0要素。
grep
とxargs
を使用した例を次に示します。
$ echo "foobarbazblargblurg" | grep -o .... | xargs
foob arba zbla rgbl
必要に応じてスペースを挿入するだけで答えるので、少なくとも行の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)
私は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