CSVファイル:
A,12345,hello
B,67890,hi
A,123456,yo
A
期待される出力:最初の列が次の場合は、2番目の列の末尾に2つのゼロを追加する必要があります。
A,1234500,hello
B,67890,hi
A,12345600,yo
答え1
データがカンマ、引用符、および改行を含むフィールドを含むことができる一般的なCSVファイルの場合は、CSV認識ツールを使用する必要があります。ミラー(mlr
)変換:
$ mlr --csv -N put -S '$1 == "A" { $2 .= "00" }' file
A,1234500,hello
B,67890,hi
A,12345600,yo
これにより、データをヘッダーなしのCSVレコードに読み込み、それを00
2番目のフィールド値の末尾に追加します(最初のフィールド値が次の場合)A
。サブコマンド-S
のオプションを使用すると、put
Millerは数値や文字列に関係なく、すべてのレコードを文字列として扱います。
Millerは内部編集に対応するオプションを使用できます-I
。
データがヘッダレス形式の場合シンプルCSV形式は、カンマ、引用符、または改行(CSVで特別な引用符が必要な形式)を含むフィールドを含まないことを意味し、それを使用して次をawk
変換できます。
$ awk -F , 'BEGIN { OFS=FS } $1 == "A" { $2 = $2 "00" }; 1' file
A,1234500,hello
B,67890,hi
A,12345600,yo
ここで、カンマで区切られたフィールドはawk
;で読み取られます。最初のフィールドがある場合、A
文字列は00
2番目のフィールドに追加されます。後続の個別出力は(修正可能)レコード1
です。awk
sed
便利でメンテナンス可能な方法で構造化文書を編集するのには実際には適していません。データがヘッダレス形式の場合シンプルA,
CSV形式の場合は、文字列で始まる行を一致させ、その行の2番目のコンマの前に2つのゼロを挿入することでこれを行うことができます。
$ sed '/^A,/ s/,/00,/2' file
A,1234500,hello
B,67890,hi
A,12345600,yo
...しかし、sed
レコードやフィールドの概念はなく、各入力行をプレーンテキスト文字列として扱います。
上記sed
の表現では/^A,/
住所後続の代替コマンドに使用されます。つまり、s
この正規表現に一致するすべての行(文字列で始まる行A,
)にコマンドが適用されます。試合の交換第二2
式が最後にあるので、その行にカンマを追加してその文字列に置き換えます00,
。
エディタでは、対応する編集コマンドは、「この正規表現に一致するすべての行に次の代替項目を適用します」ed
です。これは式の終わりを理解しても機能します(そうではありません)。g/^A,/ s/,/00,/2
vi
2
答え2
Raku(以前のPerl_6)の使用
~$ raku -ne 'my @a = .split(","); \
if @a[0] eq "A" {@a.[1] ~= "00"}; \
.put for @a.join(",");' file
上記のコードは、次の目的にのみ使用できます。シンプル-CSV、つまりエスケープ/引用符が必要な特殊文字はありません(例:埋め込みコンマ、埋め込み二重引用符、埋め込み改行)。デフォルトでは、-ne
各行に対して次のことを行います。
split
,
カンマで、- 最初の要素が「A」文字列の場合、
00
2番目の要素の末尾に関連する条件を実行してから[1]
[0]
eq
- out の
put
要素はjoin
カンマで再グループ化されます。
入力例:
A,12345,hello
B,67890,hi
A,123456,yo
出力例:
A,1234500,hello
B,67890,hi
A,12345600,yo
より複雑なCSVがある場合、またはより強力なソリューションが必要な場合は、RakuText::CSV
モジュールを使用してください。
~$ raku -MText::CSV -e 'my @a = csv( in => $*IN, sep => ","); \
for @a -> $a {$a.[1] ~= "00" if $a.[0] eq "A"}; \
csv( in => @a, out => $*OUT);' file
TSVファイルsep => ","
などの入力ファイルに適した区切り文字に変更できます。\t
出力例は上記と同じです。