如何在字段之间放置逗号?
输入数据
12123 'QA test case 1' 'QA environment'
12234 'UAT test case 1' 'UAT environment'
预期输出
12123, 'QA test case 1', 'QA environment'
12234, 'UAT test case 1', 'UAT environment'
答案 0 :(得分:3)
另一种选择是使用CSV解析器:
ruby -rcsv -ne '
puts CSV.generate_line(
CSV.parse_line($_.strip, {:col_sep => " ", :quote_char => "'\''"}
), {:force_quotes => 1})
' file
"12123","QA test case 1","QA environment"
"12234","UAT test case 1","UAT environment"
答案 1 :(得分:2)
一个天真的bash
实现,假设没有(转义的)'
个实例在字段中出现:
假设输入来自文件file
:
# Read all whitespace-separated tokens (potentially across quoted field boundaries).
while read -ra tkns; do
# Initialize per-line variables.
numTkns=${#tkns[@]} i=0 inField=0
# Loop over all tokens.
for tkn in "${tkns[@]}"; do
# Determine if we're inside a quoted field.
[[ $tkn == \'* ]] && inField=1
[[ $tkn == *\' ]] && inField=0
# Determine the output separator:
if (( ++i == numTkns )); then
sep=$'\n' # last token, terminate output line with \n
else
# inside a field: use just a space; between fields: use ', '
(( inField )) && sep=' ' || sep=', '
fi
# Output token and separator.
printf '%s%s' "$tkn" "$sep"
done
done < file
答案 2 :(得分:2)
您的输入数据看起来非常像参数列表。因此,一种方便的方法是定义一个bash函数,它只是将其参数列表作为逗号分隔的标记返回,并为文件中的每一行调用它。
但是,下面的简单实现会丢失多字标记周围的引号(但它会正确放置逗号)。如果你需要那些完全相同的引号,它会变得有点复杂(输出引用的每个标记都非常容易):
#!/bin/bash
function csv_args() {
while [ -n "$1" ]; do
echo -n "$1"
shift
[ -n "$1" ] && echo -n ', '
done
echo
}
while read line; do
eval csv_args $line
done < /path/to/your/file
答案 3 :(得分:2)
$ sed "s/ '/,&/g" file
12123, 'QA test case 1', 'QA environment'
12234, 'UAT test case 1', 'UAT environment'
答案 4 :(得分:1)
试试这个awk:
awk -F" '" '{ print $1, $2, $3 }' OFS=", '" data
或使用BEGIN
块:
awk -F" '" 'BEGIN {OFS="," FS} { print $1, $2, $3 }' data
在任何一种情况下,FS
都设置为'
(空格+&#34;&#39;&#34;),OFS
设置为&# 34;,&#34; + '
。它基于假设'
是一个有效唯一的字段分隔符,所有输入数据都按照问题格式化/排列。
答案 5 :(得分:1)
以下是我使用csv
awk
的方法
cat file
12123 'QA test case 1' 'QA environment' some more
12234 'UAT test case 1' 'UAT environment'
awk '{for (i=1;i<NF;i++) {if ($i~t) c++;printf "%s"(c%2?FS:", "),$i}print $NF}' t=\' file
12123, 'QA test case 1', 'QA environment', some, more
12234, 'UAT test case 1', 'UAT environment'
这会记录它找到的'
个。{
如果0 2 4 6 etc
您在一个群组之外,请使用,
分开
如果1 3 5 7 etc
您在一个群组中,请按(空格)
由于你现在拥有一个好的分隔符,你可以摆脱'
awk '{for (i=1;i<NF;i++) {if ($i~t) c++;sub(t,"",$i);printf "%s"(c%2?FS:","),$i}sub(t,"",$NF);print $NF}' t=\' file
12123,QA test case 1,QA environment,some,more
12234,UAT test case 1,UAT environment
您还可以使用用于定义字段的FPAT
,与定义分隔符的FS
相对,但是您需要gnu awk
4.x,并且它不可移植。
awk '{for (i=1;i<NF;i++) printf "%s, ",$i;print $NF}' FPAT="[^' ]+|'[^']+'" file
12123, 'QA test case 1', 'QA environment', some, more
12234, 'UAT test case 1', 'UAT environment'
FPAT="[^' ]+|'[^']+'"
如何运作?
1.字段不应包含一个或多个'
或空格。 [^' ]+
eks some
和more
2.字段以'
开头,然后是一个或多个'
,然后以'
结尾。 '[^']+'
eks 'test data'
答案 6 :(得分:0)
解决方案是遍历记录中的每个字符(while read -n 1
),将每个非空格字符连接为一个元素值,并将所有字符用单引号括起来(或在您的选项中引用单引号({{ 1}})。每当你完成一个单元(到达空格或换行符)时,将它附加到一个数组。当遇到一个换行符或到达EOF时,结束记录并以你的格式打印记录数组。循环再次开始记录数组清零。
想要源代码?先告诉我你的工作。 :)
答案 7 :(得分:0)
这个解决方案(我相信)不是很好,但至少是标准的:
awk 'BEGIN{SP="[:space:]"}{gsub("(["SP"]*('\''[^'\'']*'\''|[^'\''"SP"])+)","&,");if(match($0, (",["SP"]+$")))$0=substr($0,1,RSTART-1)substr($0,RSTART+1)}1'
虽然一些“破解”的awk实现不支持[[:foo:]]样式的字符类,但在这种情况下你可以使用:
awk 'BEGIN{SP=" \t\f\v\r\n"}{gsub("(["SP"]*('\''[^'\'']*'\''|[^'\''"SP"])+)","&,");if(match($0, (",["SP"]+$")))$0=substr($0,1,RSTART-1)substr($0,RSTART+1)}1'
注意:我使用'\''来放置每个单引号字符,因为这是一种简单而标准的方法。如果要在“.awk”文件中使用此行,只需使用单引号替换每个匹配项。