提问人:AnjK 提问时间:6/1/2023 最后编辑:AnjK 更新时间:6/1/2023 访问量:148
Bash 脚本将包含“和”的变量值写入文件
Bash script to write a variable value that contains " and ' to a file
问:
我正在创建一个 bash 脚本来将变量值写入 csv 文件。 但无法写入行中包含“和”符号的特定值。 例如,我在 shell 中提供了这样的变量和值:
名字:my-name
密码:j50z54"#7b'y'/3l7H%7
如果尝试将它们写入 csv 文件,如下所示:
echo -e "username,password,name" >> abc.csv
echo -e "$username,$password,$name" >> abc.csv
我收到错误:
line 2: unexpected EOF while looking for matching `"'
line 3: syntax error: unexpected end of file
由于值中存在双引号和单引号,因此会出现问题。
方法1:
按如下方式存储变量值:
- 通过在双引号和单引号前面加上反斜杠来转义所有双引号和单引号 \
- 将整个变量值括在双引号内。
例如,password 的实际值应另存为j50z54"#7b'y'/3l7H%7
"j50z54\"#7b\'y\'/3l7H%7"
然后,如果我运行以下脚本:
echo -e "username,password,name" >> abc.csv
echo -e "$username,$password,$name" >> abc.csv
sed -i 's/\\//g' abc.csv
我得到正确的csv文件:
username,password,name
[email protected],j50z54"#7b'y'/3l7H%7,my-name
但是,问题在于无法像上述格式那样修改变量值(在其源头)。
方法2:
我尝试了一个 metho,如图所示,脚本:
[email protected]
name=my-name
cat >> abc.csv << \EOF
Username,Password,Name
$username,j70z38"#7k'y'/3l7H%9,$name
EOF
给出输出文件 abc.csv:
Username,Password,Name
$username,j70z38"#7k'y'/3l7H%9,$name
(请忽略此处直接提供的密码值仅用于测试目的的事实)
在此方法中,将打印变量名称(如 $username 和 $name)而不是它们的值。
问题:
有没有其他更好的方法/脚本将变量值正确写入 CSV 文件?
附加信息:
此脚本用于在Azure DevOps管道的 bash 任务中实现自动化。此外,密码保存在变量组中,并在管道中作为 .$(password)
答:
将线索拼凑在一起,我认为您的情况大致如下:
该脚本从某些外部源(参数、交互式输入、文件等)接收用户名、密码和名称,并将它们存储在变量中。
您想要编写包含这些值的 CSV 表示形式的文件
第一次尝试使用 ,将值写入为已接收值,但之后(单独的)CSV 读取器无法成功读回它们
echo
您的“方法 1”描述了一种概念验证变体,其中用户名、密码和名称是在脚本中显式设置的,而不是像最终需要的那样从外部源读取。
您的“方法 2”可能是另一个概念验证变体
但是,我不接受这一点:
无法写入行中包含“和”符号的特定值。
为支持该声明而提供的示例实际上完美地发出了这些值,并且,另外,您提供的错误消息不可能来自这些行。我最好的猜测是错误来自 CSV 读取器,在这种情况下,它反映的不是您未能写入数据,而是生成的文件不是有效的 CSV(就该读取器而言)。但是请注意,如果数据包含任何文字反斜杠 (),那么就会搞砸。如果您想使用(您可以),请删除 .\
echo -e
echo
-e
此外,由于在未加引号的字段中包含双引号,某些 CSV 读取器会拒绝由方法 1 生成的文件,如果双引号出现在字段的开头而不是中间,则大多数 CSV 读取器会拒绝该文件。这可能是你所期望的,但按照大多数标准,它并没有很好地被描述为“正确”的 csv 文件。
您似乎正在努力解决的问题是 CSV 需要对某些字符进行特殊处理。您不能只是将原始字符数据转储到 CSV 文件中并期望读者理解它。您需要为 CSV 设置适当的数据格式。这与 Bash 无关。
另请注意,“CSV”范畴下的格式种类繁多。并非所有人都使用逗号作为字段分隔符。如果您以特定的 CSV 方言为目标,则需要根据该方言的要求设置输出格式。这肯定会包括对包含字段分隔符的字段进行某种形式的引用,并且很可能对包含引号字符的字段进行某种形式的引用。如果您的方言允许包含记录分隔符的字段,则它还需要引用这些字段。
如果您不确定您的 CSV 方言需要什么,或者您对此很灵活,那么请知道 CSV 方言主要使用双引号字符 () 进行引用,并且通常它们仅支持在整个字段的基础上引用。通常,在带引号的字段中转义双引号的指定方法是将其加倍。一些 CSV 方言希望所有字段都被引用,这与大多数方言兼容,所以除非你知道你需要做不同的事情,否则这就是我的建议。"
例:
#!/bin/bash
# Input the data
read -r -p 'username: ' username
read -r -p 'name: ' name
read -r -p 'password: ' password
# Double all quotation marks (") in the field values
username_csv=${username//\"/\"\"}
name_csv=${name//\"/\"\"}
password_csv=${password//\"/\"\"}
# Write the output file with quotes and field delimiters
cat >output.csv <<EOF
Username,Password,Name
"$username_csv","$password_csv","$name_csv"
EOF
演示
$ bash example.sh
username: [email protected]
name: my-name
password: j50z54"#7b'y'/3l7H%7
$
$ cat output.csv
Username,Password,Name
"[email protected]","j50z54""#7b'y'/3l7H%7","my-name"
评论
cat >> abc.csv << \EOF
EOF
cat >> abc.csv << EOF
评论
password="j50z54\"#7b'y'/3l7H%7"; echo -e "$password"
\"
""
echo
echo -e
printf '%s\n' "$username,$password,$name"
printf '%s,%s,%s\n' "$username" "$password" "$name"
%b
%s