入力する - -
System:root,bin,user,saaa
出力表示----
System,root
System,bin
System,user
System,says
この出力を取得する方法は?
答え1
使うのはいいけどperl
シェルスクリプトを指定したので...
ステップ1:文字に従って行を2つの部分に分割します:
。cut
コマンドまたは${parameter#word}
構造を使用してください${parameter%word}
。
ステップ2:行の2番目の部分を役割に応じて複数の部分に分割します,
。そのawk
コマンドを使用してください - どのくらいのブロックがあるのか教えてください。 (私は専門家ではないawk
ので、これが私が思うように動作するかどうかはわかりません。)
ステップ3:手順2で得られた部品を繰り返し、手順1の最初の部品に貼り付けて印刷します。
答え2
入力行に正確に1つのコロン(:
)が含まれていて、,
コロンの前にカンマ()が来ることができず、カンマとコロンの両方が抽出された部分文字列の一部になることができない(エスケープされていない)と仮定できれば、awk
スクリプトで十分です。
$ printf '%s\n' 'System:one,two,three' |
awk -v FS=':|,' '{ for (i=2;i<=NF;i++) { print $1","$i } }'
出力:
System,one
System,two
System,three
フィールドFS
区切り記号は:
すべての文字または,
。
代わりに、最初のコロン(カンマを含む)の前のすべての項目を最初の出力フィールドとして選択し、入力行の残りの部分をコンマに分割したい場合(カンマが部分的に残っていないと仮定)、部分文字列(なしにもかかわらず)エスケープ)、提案されているようにシェル機能を使用できます。ハイミの答え:
$ printf '%s\n' 'System:one,two,three' |
while IFS= read -r rem; do # IFS= to preserve blank characters
first=${rem%%:*} # Remove from the first ':' on
rem=${rem#"$first"} # Remove first from the beginning of rem
rem=${rem#:} # Strip the remaining ':' at rem's beginning
while test "$rem"; do # Exit when rem is empty
second=${rem%%,*} # Remove from the first ',' on
rem=${rem#"$second"} # Remove second from the beginning of rem
rem=${rem#,} # Strip the remaining ',' at rem's beginning
printf '%s\n' "$first,$second"
done
done
ただ理解していることを確認してくださいシェルループを使用してテキストを処理する際の注意事項。
またはGNUを使用してくださいsed
。
$ printf '%s\n' 'System:one,two,three' |
sed -n '
:l1
s/^[^:]*:\n//g;
t l2;
s/^\([^:]\{1,\}\):\([^,\n]\{1,\}\)*,\{0,1\}\(.*\)$/\1:\3\n\1,\2/;
t l1;
q;
:l2 p;
'
ここでは、分岐(t
)からラベル(l1
)までを使用して、ループを介して入力の各行を処理します。一度に1つずつ、最初:
と最初の次の間の部分文字列がパターン,
スペースに新しい行として追加され、最初の前の部分文字列の後に連結されます:
。抽出する部分文字列がもう存在しない場合は、元の文字列の残りの部分が削除され、パターンスペースが印刷され、プログラムが終了します。
(GNUsed
バージョン> = 4.6の場合は、optionsを使用して呼び出して進行状況を段階的に確認できます--debug
)。
\n
内部角かっこ式を使用して文字を一致させること(ここでは否定一致)<newline>
は標準ではありません。 POSIX は、<backslash>
そのコンテキストで特別な意味が失われることを指定します。