linux sed 命令 - 在 csv 行的每一端添加字符串
linux sed command - adding string on every end of the line of csv
目前我在 ff CSV 数据上遇到问题。
COLUMN1,COLUMN2,COLUMN3,COLUMN4
apple1,apple2,apple3,apple4
banana1,banana2,banana3,
caimito1,"caimito21
caimito22","caimito31
caimito32",caimito4
看起来像这样:
╔══════════╦═══════════╦═══════════╦══════════╗
║ COLUMN1 ║ COLUMN2 ║ COLUMN3 ║ COLUMN4 ║
╠══════════╬═══════════╬═══════════╬══════════╬
║ apple1 ║ apple2 ║ apple3 ║ apple4 ║
║ banana1 ║ banana2 ║ banana3 ║ ║
║ caimito1 ║ caimito21 ║ caimito31 ║ caimito4 ║
║ ║ caimito22 ║ caimito32 ║ ║
╚══════════╩═══════════╩═══════════╩══════════╝
所以我的计划是添加 COLUMN5,它的每一行都有一个值 "FRUIT"。
使用的命令:
sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/$/,FRUIT/g" > OUTPUT.csv
输出:
╔══════════╦════════════════╦════════════════╦══════════╦═════════╗
║ COLUMN1 ║ COLUMN2 ║ COLUMN3 ║ COLUMN4 ║ COLUMN5 ║
╠══════════╬════════════════╬════════════════╬══════════╬═════════╣
║ apple1 ║ apple2 ║ apple3 ║ apple4 ║ FRUIT ║
║ banana1 ║ banana2 ║ banana3 ║ ║ FRUIT ║
║ caimito1 ║ caimito21FRUIT ║ caimito31FRUIT ║ caimito4 ║ FRUIT ║
║ ║ caimito22 ║ caimito32 ║ ║ ║
╚══════════╩════════════════╩════════════════╩══════════╩═════════╝
有没有办法在不影响 "caimito" 行的情况下添加 "FRUIT"?
我也试过ff。命令,但没有成功。在“$”之前添加了“,”。
sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/,$/,FRUIT/g" > OUTPUT.csv
Sed 可能不是处理 csv 文件的正确工具,因为规则比看起来要复杂得多(这可能是可能的,但此类脚本通常很容易出错,等等)。但是,您可以使用 csvtools
来处理此问题:
file="FILE.csv"
nr=$(csvtool height $file)
ot=$(perl -e "print \"COLUMN5\n\";for$i(2..$nr){print \"FRUIT\n\";}")
echo "$ot" | csvtool paste "$file" -
脚本的工作原理如下:
- 首先我们用
csvtool height
, 计算行数
- 接下来我们通过打印
COLUMN5
后跟 n-1 次 FRUIT
. 来生成附加列
- 最后我们将该内容粘贴到文件的右侧。
编辑:我只看到了 csvtool 解决方案;它当然更实用。我留下这个解决方案主要是因为隐藏它和它的 Lovecraftian 美会很可惜。
好了,开始吧。这是在 sed 中执行此操作的一种方法:
sed ':a $!{ N; ba }; s/"[^"]*"/{&}/g; :b s/\({"[^"]*\)\n\([^"]*"}\)/~"~/g; tb; s/\n\|$/,FRUIT&/g; s/,FRUIT\(\n\|$\)/,COLUMN5/; :c s/\({"[^"]\)*~"~/\n/g; tc; s/{"\|"}/"/g' filename
这将是一段旅程。它的工作原理如下:
:a $!{ N; ba } # assemble the whole file in the
# hold buffer
s/"[^"]*"/{&}/g # encase all "-enclosed fields in
# {"..."} to make matching the beginning
# and end separately possible.
:b # jump mark for looping
s/\({"[^"]*\)\n\([^"]*"}\)/~"~/g # replace the first newline in all
# {"..."} fields with ~"~
tb # loop until all were replaced
s/\n\|$/,FRUIT&/g # Put FRUIT at the end of all lines
s/,FRUIT\(\n\|$\)/,COLUMN5/ # Replace the first ,FRUIT with ,COLUMN5
# The \(\n\|$\) bit is so that this
# works with empty files (that only
# have a header line)
:c # Jump mark for looping
s/\({"[^"]\)*~"~/\n/g # replace the first ~"~ in all {"..."}
# fields with a newline
tc # loop until all were replaced
s/{"\|"}/"/g # replace all {", "} markers with "
# again.
sed '1 {
s/$/,COLUMN5/
b
}
:load
/^\([^"]*"[^"]*"\)*[^"]*"[^"]*$/ {
N
b load
}
s/$/,,,,/;s/^\(\([^,]*,\)\{4\}\).*/FRUIT/' YourFile
- 在第 1 行添加
COLUMN5
比循环 (b
)
- 如果当前工作缓冲区上有打开的
"
,请加载新行并重试此操作
- 默认加4
,
- 将第 4 个第一组用
,
分开并添加 FRUIT
- (周期)
posix 版本所以 --posix
在 GNU sed
对于 "valid" csv(1 行,所有参数由 ,
分隔),只需删除负载循环部分
目前我在 ff CSV 数据上遇到问题。
COLUMN1,COLUMN2,COLUMN3,COLUMN4
apple1,apple2,apple3,apple4
banana1,banana2,banana3,
caimito1,"caimito21
caimito22","caimito31
caimito32",caimito4
看起来像这样:
╔══════════╦═══════════╦═══════════╦══════════╗
║ COLUMN1 ║ COLUMN2 ║ COLUMN3 ║ COLUMN4 ║
╠══════════╬═══════════╬═══════════╬══════════╬
║ apple1 ║ apple2 ║ apple3 ║ apple4 ║
║ banana1 ║ banana2 ║ banana3 ║ ║
║ caimito1 ║ caimito21 ║ caimito31 ║ caimito4 ║
║ ║ caimito22 ║ caimito32 ║ ║
╚══════════╩═══════════╩═══════════╩══════════╝
所以我的计划是添加 COLUMN5,它的每一行都有一个值 "FRUIT"。
使用的命令:
sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/$/,FRUIT/g" > OUTPUT.csv
输出:
╔══════════╦════════════════╦════════════════╦══════════╦═════════╗
║ COLUMN1 ║ COLUMN2 ║ COLUMN3 ║ COLUMN4 ║ COLUMN5 ║
╠══════════╬════════════════╬════════════════╬══════════╬═════════╣
║ apple1 ║ apple2 ║ apple3 ║ apple4 ║ FRUIT ║
║ banana1 ║ banana2 ║ banana3 ║ ║ FRUIT ║
║ caimito1 ║ caimito21FRUIT ║ caimito31FRUIT ║ caimito4 ║ FRUIT ║
║ ║ caimito22 ║ caimito32 ║ ║ ║
╚══════════╩════════════════╩════════════════╩══════════╩═════════╝
有没有办法在不影响 "caimito" 行的情况下添加 "FRUIT"?
我也试过ff。命令,但没有成功。在“$”之前添加了“,”。
sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/,$/,FRUIT/g" > OUTPUT.csv
Sed 可能不是处理 csv 文件的正确工具,因为规则比看起来要复杂得多(这可能是可能的,但此类脚本通常很容易出错,等等)。但是,您可以使用 csvtools
来处理此问题:
file="FILE.csv"
nr=$(csvtool height $file)
ot=$(perl -e "print \"COLUMN5\n\";for$i(2..$nr){print \"FRUIT\n\";}")
echo "$ot" | csvtool paste "$file" -
脚本的工作原理如下:
- 首先我们用
csvtool height
, 计算行数
- 接下来我们通过打印
COLUMN5
后跟 n-1 次FRUIT
. 来生成附加列
- 最后我们将该内容粘贴到文件的右侧。
编辑:我只看到了 csvtool 解决方案;它当然更实用。我留下这个解决方案主要是因为隐藏它和它的 Lovecraftian 美会很可惜。
好了,开始吧。这是在 sed 中执行此操作的一种方法:
sed ':a $!{ N; ba }; s/"[^"]*"/{&}/g; :b s/\({"[^"]*\)\n\([^"]*"}\)/~"~/g; tb; s/\n\|$/,FRUIT&/g; s/,FRUIT\(\n\|$\)/,COLUMN5/; :c s/\({"[^"]\)*~"~/\n/g; tc; s/{"\|"}/"/g' filename
这将是一段旅程。它的工作原理如下:
:a $!{ N; ba } # assemble the whole file in the
# hold buffer
s/"[^"]*"/{&}/g # encase all "-enclosed fields in
# {"..."} to make matching the beginning
# and end separately possible.
:b # jump mark for looping
s/\({"[^"]*\)\n\([^"]*"}\)/~"~/g # replace the first newline in all
# {"..."} fields with ~"~
tb # loop until all were replaced
s/\n\|$/,FRUIT&/g # Put FRUIT at the end of all lines
s/,FRUIT\(\n\|$\)/,COLUMN5/ # Replace the first ,FRUIT with ,COLUMN5
# The \(\n\|$\) bit is so that this
# works with empty files (that only
# have a header line)
:c # Jump mark for looping
s/\({"[^"]\)*~"~/\n/g # replace the first ~"~ in all {"..."}
# fields with a newline
tc # loop until all were replaced
s/{"\|"}/"/g # replace all {", "} markers with "
# again.
sed '1 {
s/$/,COLUMN5/
b
}
:load
/^\([^"]*"[^"]*"\)*[^"]*"[^"]*$/ {
N
b load
}
s/$/,,,,/;s/^\(\([^,]*,\)\{4\}\).*/FRUIT/' YourFile
- 在第 1 行添加
COLUMN5
比循环 (b
) - 如果当前工作缓冲区上有打开的
"
,请加载新行并重试此操作 - 默认加4
,
- 将第 4 个第一组用
,
分开并添加FRUIT
- (周期)
posix 版本所以 --posix
在 GNU sed
对于 "valid" csv(1 行,所有参数由 ,
分隔),只需删除负载循环部分