如何更新 bash 文件中的多字符分隔符字段?
How to update a multichracter delimited field in a file in bash?
我正在尝试匹配某个字段并从以多个字符分隔的文件中更新其数据。我正在使用它来模仿 SQL 的更新。这是使用 bash.
创建迷你 DBMS 的更大项目的一部分
我试过的:
sed "s/\^\_\^/:/g" $file_path | cut -d: -f1 | grep -nw SAR | sed "s/\^\_\^/:/g" | cut -d: -f2 | sed -i "s/$match/$update/g"
我的问题是我无法使用 sed -i
仅更新找到的这些特定列,因为您无法通过管道输入它。
正在使用的分隔符是:^_^
数据文件示例:
'EGP'^_^'Egypt'
'SAR'^_^'Europe'
'SAR'^_^'Europe'
'SAR'^_^'Europe'
'SAR'^_^'Europe'
'Europe'^_^'SAR'
'SAR'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
例如,我的 $match
可以是 SAR
,而 $update
可以是 USD
数据文件的预期更改
'EGP'^_^'Egypt'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'Europe'^_^'SAR'
'USD'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
如果有更好的不同方法,那也很受欢迎,因为我对 bash 脚本编写还很陌生。
最好在此处使用 awk
:
awk -v s="'SAR'" -v q="'USD'" -F'\^_\^' -v OFS='^_^' '==s {=q} 1' file
'EGP'^_^'Egypt'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'Europe'^_^'SAR'
'USD'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
解释:
-v s="'SAR'"
设置命令行变量 s='SAR'
-v q="'USD'"
设置命令行变量 s='USD'
-F '\^_\^'
将输入字段分隔符设置为 ^_^
。我们需要对 ^
进行转义,因为这是一个特殊的正则表达式元字符,我们需要对它进行双重转义,因为我们在稍后转换为正则表达式(字段分隔符)的字符串中使用它。
-v OFS='^_^'
将输出字段分隔符设置为 ^_^
== s
将第一个字段与 'SAR'
进行比较
= q
将 </code> 设置为变量 <code>'USD'
使用 sed,您可以在字符串 ^
的开头使用 $match
,并将其更改为 $update
:
match="'SAR'"
update="'USD'"
sed "s/^$match\^_\^/$update^_^/" file
输出
'EGP'^_^'Egypt'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'Europe'^_^'SAR'
'USD'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
看到一个bash demo。
使用您展示的示例,请尝试执行以下 awk
程序。
awk -v matchvalue="'SAR'" -v updatedvalue="'USD'" '
match([=10=],"^"matchvalue"\^_\^"){
print updatedvalue"^_^" substr([=10=],RSTART+RLENGTH)
next
}
1
' Input_file
解释: 创建 2 个名为 matchvalue
和 updatedvalue
的变量以及 'SAR'
和 'USD'
样本中 OP 显示的值。然后在主程序中使用 match
函数匹配如果一行以 'SAR'^_^
开头然后在其位置打印新值然后打印该行的其余部分,如果行不是从 'SAR'^_^
开始然后简单地打印出来。
这是我最后做的:
escaped_delm=$(echo $curr_delim | sed 's/[^^\]/[&]/g; s/\^/\^/g; s/\/\\/g')
awk -F"$escaped_delm" -v a_col_update=$update_field -v pick=$p_tmp_field -v a_del="$match" -v a_ins="$insert" -v OFS="$curr_delim" '$pick==a_del {$a_col_update=a_ins} 1' $t_path > tmp && mv tmp $t_path
我面临的最大问题是我将定界符 ^_^
作为变量传递给 awk。我的脚本假定我不知道变量是什么,并且它是在脚本开头传递给它的。这会导致问题,就像第一个答案建议 awk
的 -F
选项认为 ^
是一个正则表达式参数。
这就是我使用的 sed
命令非常方便的地方!它通过转义任何正则表达式元字符来清理分隔符。感谢 Ed Morton 对 的出色回答,我从中获得了 sed
命令。
希望其他人觉得这有用!
我的 awk 变量是:
curr_delim="^_^"
a_col_update=<column number to be updated>
pick=<column used to pick the record/row>
a_del=<field to be updated from picked record/row>
a_ins=<new value for the picked field>
OFS="$curr_delim"
我正在尝试匹配某个字段并从以多个字符分隔的文件中更新其数据。我正在使用它来模仿 SQL 的更新。这是使用 bash.
创建迷你 DBMS 的更大项目的一部分我试过的:
sed "s/\^\_\^/:/g" $file_path | cut -d: -f1 | grep -nw SAR | sed "s/\^\_\^/:/g" | cut -d: -f2 | sed -i "s/$match/$update/g"
我的问题是我无法使用 sed -i
仅更新找到的这些特定列,因为您无法通过管道输入它。
正在使用的分隔符是:^_^
数据文件示例:
'EGP'^_^'Egypt'
'SAR'^_^'Europe'
'SAR'^_^'Europe'
'SAR'^_^'Europe'
'SAR'^_^'Europe'
'Europe'^_^'SAR'
'SAR'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
例如,我的 $match
可以是 SAR
,而 $update
可以是 USD
数据文件的预期更改
'EGP'^_^'Egypt'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'Europe'^_^'SAR'
'USD'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
如果有更好的不同方法,那也很受欢迎,因为我对 bash 脚本编写还很陌生。
最好在此处使用 awk
:
awk -v s="'SAR'" -v q="'USD'" -F'\^_\^' -v OFS='^_^' '==s {=q} 1' file
'EGP'^_^'Egypt'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'Europe'^_^'SAR'
'USD'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
解释:
-v s="'SAR'"
设置命令行变量s='SAR'
-v q="'USD'"
设置命令行变量s='USD'
-F '\^_\^'
将输入字段分隔符设置为^_^
。我们需要对^
进行转义,因为这是一个特殊的正则表达式元字符,我们需要对它进行双重转义,因为我们在稍后转换为正则表达式(字段分隔符)的字符串中使用它。-v OFS='^_^'
将输出字段分隔符设置为^_^
== s
将第一个字段与'SAR'
进行比较
= q
将</code> 设置为变量 <code>'USD'
使用 sed,您可以在字符串 ^
的开头使用 $match
,并将其更改为 $update
:
match="'SAR'"
update="'USD'"
sed "s/^$match\^_\^/$update^_^/" file
输出
'EGP'^_^'Egypt'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'USD'^_^'Europe'
'Europe'^_^'SAR'
'USD'^_^'Europe'
'MYR'^_^'Malaysia'
'MYR'^_^'Malasia'
看到一个bash demo。
使用您展示的示例,请尝试执行以下 awk
程序。
awk -v matchvalue="'SAR'" -v updatedvalue="'USD'" '
match([=10=],"^"matchvalue"\^_\^"){
print updatedvalue"^_^" substr([=10=],RSTART+RLENGTH)
next
}
1
' Input_file
解释: 创建 2 个名为 matchvalue
和 updatedvalue
的变量以及 'SAR'
和 'USD'
样本中 OP 显示的值。然后在主程序中使用 match
函数匹配如果一行以 'SAR'^_^
开头然后在其位置打印新值然后打印该行的其余部分,如果行不是从 'SAR'^_^
开始然后简单地打印出来。
这是我最后做的:
escaped_delm=$(echo $curr_delim | sed 's/[^^\]/[&]/g; s/\^/\^/g; s/\/\\/g')
awk -F"$escaped_delm" -v a_col_update=$update_field -v pick=$p_tmp_field -v a_del="$match" -v a_ins="$insert" -v OFS="$curr_delim" '$pick==a_del {$a_col_update=a_ins} 1' $t_path > tmp && mv tmp $t_path
我面临的最大问题是我将定界符 ^_^
作为变量传递给 awk。我的脚本假定我不知道变量是什么,并且它是在脚本开头传递给它的。这会导致问题,就像第一个答案建议 awk
的 -F
选项认为 ^
是一个正则表达式参数。
这就是我使用的 sed
命令非常方便的地方!它通过转义任何正则表达式元字符来清理分隔符。感谢 Ed Morton 对 sed
命令。
希望其他人觉得这有用!
我的 awk 变量是:
curr_delim="^_^"
a_col_update=<column number to be updated>
pick=<column used to pick the record/row>
a_del=<field to be updated from picked record/row>
a_ins=<new value for the picked field>
OFS="$curr_delim"