単語の文字、つまり各行の最後の4文字をどのように分割しますか?

単語の文字、つまり各行の最後の4文字をどのように分割しますか?

単語の合計を空白と各行の最後の4文字に分割する方法は?例えば、与えられた

 1. placing
 2. backtick
 3. paragraphs

下に見たい

 1. pla cing
 2. back tick
 3. pa ragr aphs

答え1

アッ解決策:

awk '{ c=0; for(i=length($2);i>0;i-=4) {a[++c]=(i-4>0)? substr($2,i-4+1,4) : substr($2,1,i)} 
    $2=""; for(i=length(a);i>0;i--) $2=$2 FS a[i] }1' file

出力:

1.  pla cing
2.  back tick
3.  pa ragr aphs

答え2

Perlこれを使用して、lookarounds次のことができます。

perl -pe 's/(?<=\w)(?=(?:\w{4})+$)/ /g'

つまり、特定の位置に立っているとき、左側には英数字があり、右側には文字列の最後まで少なくとも4つ以上の数字またはその倍数があります。そんな場所が存在する限り、そこに空間が置かれることになる。これを行うと、要求された変更はグローバルに影響を受けます。

私達はまたbashこれをすることができます:

#!/bin/bash

# symbolic constants
NL=$'\012'; # newline
SP=$'\040'; # space

# elementary regexes
alnum='[0-9a-zA-Z]'; # a single alphanumeric
alnums4=$(csh -c 'repeat 4 echo -n "$1"' "$alnum"); # 4 consecutive alnums

# main processing
while IFS= read -r line res; do
   while c4=$(expr "$SP$line$NL" : ".*$alnum\($alnums4\)$NL")
   do
      res=${c4}${res:+"$SP"}${res-} line=${line%????}
   done
   printf '%s %s\n' "$line" "$res"
done

GNU sedエディタを使用してください。

sed -Ee '
   s/\S+/\n&\n/2; # enclose the 2nd field with markers

   # a do-while loop to progessively move the right marker to the left,
   # consuming 4 alnums in each iteration. Looping stops when 4 alnums+
   # 1 alnum at the boundary remains.
   :loop
      s/(\n[[:alnum:]].*)([[:alnum:]]{4})\n/\1\n \2/
   tloop

   # clear out the markers when done
   s/\n//g
'

答え3

を使用すると、sed次のことができます。

sed '
  G
  :1
      s/\([[:alpha:]]\)\([[:alpha:]]\{4\}\)\(\n\)/\1\3 \2/
  t1
  s/\n//
'

改行文字を実行マーカーとして使用します(改行文字は初期パターンスペースには表示されない文字です)。もともと最後に追加しました。その後、ABCDE<marker>ABCDEが5つのアルファベット文字の場合、文字シーケンスではなく空白ではなくシーケンスで単語を処理したい場合は、置換できる文字を見つけるたびに[[:space:]]それをアンループに置き換えます。最後にマーカーを削除しました。[^[:blank:]]A<marker> BCDE

これにより、行末の単語のみが処理されます。

最後の単語だけでなく、すべての単語を分類するのははるかに簡単です。

sed -e :1 -e 's/\(.*[[:alpha:]]\)\([[:alpha:]]\{4\}\)/\1 \2/;t1'

printf 'abcd\u00e9e\u0301f\n'入力に分解された文字(例:出力abcdééf)が含まれている場合は、次のことができます。

perl -Mopen=locale -lpe 'while(s/.*(?=\w)\X\K(?:(?=\w)\X){4}/ $&/){}'

答え4

Perlを使用する(単一バイト文字のみを使用すると仮定):

perl -ne 'print scalar(reverse join " ", (reverse =~ /.{1,4}/g)), "\n"'
  • 内部的には、reverse与えられた単語(実際には含まれている完全な入力行)が反転されます。
  • 正規表現は、反対の単語を4つの文字の塊に分割します(元の単語の先頭から始まる最後の塊には少ない文字を含めることができます)。
  • joinこのチャンクを文字列で連結しますが、その間にスペースがあります。
  • reverse連結文字列を外部に反転します。
  • スカラーコンテキストでscalar外部を強制的に実行するために使用されます。reverse
  • 結果が出力されますprint

以下のコードは同じことを行いますが、キャンセルして使用し、scalar次に割り当てます。"\n"print-p-l$_

perl -lpe '$_ = reverse join " ", reverse =~ /.{1,4}/g'

関連情報