我有以下属性键
connection.party= 0.0.0.0
remote.app.328.port= 5432
remote.server.url="https://someurl.com?q=78.78"
remote.conncetion.7="basic"
remote.52.base= "local"
level1.34access23="true"
88.location.code=24
location.234.code.52=24
Run Code Online (Sandbox Code Playgroud)
我需要将其转换为以下内容
connection.party= 0.0.0.0
remote.app."328".port= 5432
remote.server.url="https://someurl.com?q=78.78"
remote.conncetion."7"="basic"
remote."52".base= "local"
level1.34access23="true"
"88".location.code=24
location."234".code."52"=24
Run Code Online (Sandbox Code Playgroud)
嵌套属性键中具有前置或后置或两个点号的所有数字都需要使用双引号。不应更新与键中的文本连接的数字。(level1.34access23="true" => 无变化) 值无法更新。
我尝试使用以下内容,但它为所有内容添加了双引号。
sed -E 's/^([^=]+)\.([0-9]+)/\1."\2"/' input.properties
Run Code Online (Sandbox Code Playgroud)
有人可以帮忙吗?
您的正则表达式显然也不需要在数字后加点,并且与表达式开头的数字不匹配。
\n这是一个简单的脚本,它在两侧用点锚定数字,并且只要等号之前仍然有未引用的数字,就继续替换。
\nsed -E -e 's/^([0-9]+)\\./"\\1"./' \\\n -e :b -e 's/^([^=]+)\\.([0-9]+)\\./\\1."\\2"./' -e tb \\\n -e 's/^([^=]+)\\.([0-9]+)=/\\1."\\2"=/' input.properties\nRun Code Online (Sandbox Code Playgroud)\n更详细地说,
\ns/^([0-9]+)\\./"\\1"./\nRun Code Online (Sandbox Code Playgroud)\n:b\nRun Code Online (Sandbox Code Playgroud)\ns/^([^=]+)\\.([0-9]+)\\./\\1."\\2"./\nRun Code Online (Sandbox Code Playgroud)\ntb\nRun Code Online (Sandbox Code Playgroud)\n这确保了只要仍然有需要引用的数字,我们就能继续下去。s/^([^=]+)\\.([0-9]+)=/\\1."\\2"=/\nRun Code Online (Sandbox Code Playgroud)\n如果您在运行此脚本时遇到问题,请尝试将整个脚本放在单引号中:
\nsed -E -e 's/^([0-9]+)\\./"\\1"./\n:b \n s/^([^=]+)\\.([0-9]+)\\./\\1."\\2"./\n tb\n s/^([^=]+)\\.([0-9]+)=/\\1."\\2"=/' input.properties\nRun Code Online (Sandbox Code Playgroud)\n正如您所看到的,sed它几乎是一种只写语言。这是一个实现相同逻辑的简单 Awk 脚本。
awk 'BEGIN { FS=OFS="=" }\n{ n = split($1, a, "."); f=""\n for(i=1; i<=n; ++i)\n f = (f ? f "." : "") (a[i] ~ /^[0-9]+$/ ? "\\"" a[i] "\\"" : a[i])\n $1 = f}1' input.properties\nRun Code Online (Sandbox Code Playgroud)\n这也有些浓缩,但并不难理解(如果您认为它太晦涩,Awk 可以更轻松地手写内容)。
\n在开始处理任何输入之前,将输入字段分隔符FS和输出字段分隔符设置OFS为等号。
BEGIN { FS=OFS="=" }\nRun Code Online (Sandbox Code Playgroud)\n这会导致$1包含第一个等号之前的所有内容,并且$2,$3等包含后续等号分隔字段。
然后,对于每个输入行
\n将点上的第一个字段$1(即第一个等号之前的所有内容)拆分到数组中a。数组的长度为n。
{ n = split($1, a, ".");\nRun Code Online (Sandbox Code Playgroud)\n创建一个空字符串变量,f我们将在其中累积 的替换值$1。
f=""\nRun Code Online (Sandbox Code Playgroud)\n循环 中的字段a,即从 1 到n:
for(i=1; i<=n; ++i)\nRun Code Online (Sandbox Code Playgroud)\n在循环中,f使用附加文本进行更新。
f非空,则在 ; 的值后面添加一个点f。否则,只需保留一个空字符串,并与 ...\n 连接f = (f ? f "." : "")\nRun Code Online (Sandbox Code Playgroud)\n这使用三级运算符,如果为 true,则(expression ? value : othervalue)生成,否则生成。因此,换句话说,如果为非空,则产生 的当前值和文字点的串联;否则,产生一个空字符串。valueexpressionothervalueff"."a[i]带或不带双引号的结果,具体取决于它是否完全是数字。\n(a[i] ~ /^[0-9]+$/ ? "\\"" a[i] "\\"" : a[i])\nRun Code Online (Sandbox Code Playgroud)\n循环遍历值后,f将包含 的前一个值,$1但包含双引号引起来的任何全数字字段a。将其分配回$1.
$1 = f\nRun Code Online (Sandbox Code Playgroud)\n最后,打印修改后的行。
\n}1\nRun Code Online (Sandbox Code Playgroud)\n右大括号终止我们对每个输入行执行的操作,而 \xc2\xb41` 只是一个简单的习惯用法,它使 Awk 打印每一行。
\n(更详细地说,该值1作为条件应用,该条件始终为 true,没有任何操作,这意味着默认操作,即打印当前输入记录。)