単語をファイルの行と場所の番号に置き換える必要があります。
ファイル 1 には以下が含まれます。
ABC XYZ UIO WER GFH
DFG JHKS
WEQ RWT DSW
ANSN WERER WERT QAZX UWRE AA
その内容を次のように交換する必要があります。
S_11 S_12 S_13 S_14 S_15
S_21 S_22
S_31 S_32 S_33
S_41 S_42 S_43 S_44 S_45 S_46
その言葉は再び繰り返されません。各ファイルには異なるセットと単語数があります。
答え1
perl
- に基づく別の方法:
perl -pe 'my $i; s{\S+}{"S_$." . ++$i}ge'
S_<line-number><word-number>
これは、既存の空白を維持しながら、各行のASCIIではなく空白文字のすべてのシーケンスを置き換えます。
入力にASCII以外の空白文字を含めることができる場合は、次のようになります。
U+0085 次行
U+00A0 改行なしの空白
U+1680 OGHAM 空白表示
U+2000 EN QUAD
U+2001 EM QUAD
U+2002 EN 空白
U+2003 EM 空白
U+2004 空白 3 個ごとに
U+2005 空白 はい犬
U +2006六つのスペース
U + 2007
数字スペースU + 2008句読点スペース
U + 2009細いスペース
U + 200A髪の毛スペース
U + 2028行区切り文字
U + 2029段落区切り文字
U + 202F改行なしの狭いスペース
U + 205F中級数
U+ 3000表の文字スペース
ユーザーのロケールに従ってエンコードされ、その-Mopen=locale
オプションを追加できます。
「改行しない」スペース(上記のU + 00A0、U + 2007、およびU + 202F)は区切り文字と見なすべきではないので、除外することも除外しないこともあります。perl
PCRE(含む(*UCP)
)にはこれが含まれますが、GNUロケール[:space:]
CTYPE
カテゴリには含まれていません。私のシステムでは、U + 0085がロケールに含まれておらず、[:space:]
PCREにもU + 180Eモンゴル語コレクションの区切り記号(ここ)が含まれていることがわかりました。Unicodeでは空白として分類されていますが、もはや分類されません。)。キャラクターperl
も見てください\PZ
いいえ(大文字p
)区切り文字と\P{Zs}
文字に分類いいえスペース区切り文字に分類されます(TABを含む制御文字は区切り文字とは見なされません)。私はこれが\p{Zs}
それ自体のサブセットであることがわかりました。\pZ
はい。サブセットです。\s
答え2
$ perl -lane '$i=1; print join(" ", map { "S_$." . $i++ } @F)' file1
S_11 S_12 S_13 S_14 S_15
S_21 S_22
S_31 S_32 S_33
S_41 S_42 S_43 S_44 S_45 S_46
-l
行末の自動処理-a
入力行を@Fという配列に自動分割-n
と同様に、何も印刷せずに各入力行を繰り返しますsed -n
。-e
次のパラメータは実行するスクリプトです。
各行は(空白から)自動的に配列に分割されます(各入力行が自動的に$ 1、$ 2、...、$ NFに分割される@F
方法に似ています)。awk
スクリプトは$i
各入力行の先頭から 1 にリセットされます。
map
この関数は、@Fの各要素に対して1つの要素を持つリテラル文字列、行番号()、および変数(使用するたびに$ i増分)で構成される文字列のリストを返します。S_
$.
$i
++
その後、リストの各要素がスペースで連結されて印刷されます。
出力は標準出力に移動します。入力ファイルを変更するには、-i
間perl
にオプションを追加します-l
。または、-i.bak
上書きする前に元のファイルをバックアップしたい場合でも可能です。
しかし、出力の行番号($。)と単語カウンタ($ i)の間に区切り文字がないため、最初の行の11番目の単語( "S_111")と最初の行を区別する方法はありません。単語(「S_111」とも呼ばれる)。.
2つの値の間に区切り文字(または他のもの)を追加することをお勧めします。_
さらに、数字は常に同じ桁数を持つようにゼロで埋めることができます。たとえば、sprintf()
内部関数を使用しますmap
。
$ perl -lane '$i=1; print join(" ", map { sprintf "S_%03i.%03i", $., $i++ } @F)' file1
S_001.001 S_001.002 S_001.003 S_001.004 S_001.005
S_002.001 S_002.002
S_003.001 S_003.002 S_003.003
S_004.001 S_004.002 S_004.003 S_004.004 S_004.005 S_004.006
答え3
S_1234
たとえば、与えられた出力が12行の34列、123行の4列、または他のものを意味するかどうかをどうやって知ることができますか?_
出力で行と列番号の間に区切り文字を使用しないことは、次にこのデータで実行する操作について悪い考えのようです。
これにより、あなたが要求したアクションが実行されます。
$ awk '{for (i=1; i<=NF; i++) $i="S_" NR i} 1' file
S_11 S_12 S_13 S_14 S_15
S_21 S_22
S_31 S_32 S_33
S_41 S_42 S_43 S_44 S_45 S_46
しかし、次の点を考慮してください。
$ awk '{for (i=1; i<=NF; i++) $i="S_" NR "_" i} 1' file
S_1_1 S_1_2 S_1_3 S_1_4 S_1_5
S_2_1 S_2_2
S_3_1 S_3_2 S_3_3
S_4_1 S_4_2 S_4_3 S_4_4 S_4_5 S_4_6
したがって、出力の行と列番号を独立した値で確実に区別できます。
上記のコードは、各行から先行/末尾のスペースを削除し、すべての連続したスペースチェーンを単一のスペース文字に変換します。これが問題なのか疑問です。問題が発生した場合はお知らせください。
答え4
あなたはそれを使用することができますawk
:
awk '{for (i=1; i<=NF; i++){ printf "S_"NR i " " } print "" }' file1 > newfile
mv newfile file1
または、以下を使用する場合(通常はgawk
Linuxにawk
接続されていますgawk
):
gawk -i inplace '{for (i=1; i<=NF; i++){ printf "S_"NR i " " } print "" }' file1
awk では、1行あたりのfor (i=1; i<=NF; i++)
合計列数を繰り返すために使用されます。NF
各行の現在の列数を保存します。 awk
の場合、Iを使用して現在の行番号を取得し、それを使用して現在の列インデックスを取得します。printf "S_"NR i " "
NR
i