shell: 替换文件中的部分行
shell: Replacing a part of Line in a file
我是 shell 编程新手,必须完成以下任务。
我在第 28 行(静态)有一个包含以下行的文件。
page.sysauth = "Admin"
我想在每次创建 sysauth 的新条目时使用 shell 脚本替换这一行。
page.sysauth = {"Admin", "root"}
page.sysauth = {"Admin", "root", "newAdmin"}
等等
我还想从这个 sysauth 变量中删除条目
page.sysauth = {"Admin", "root", "newAdmin"}
page.sysauth = {"Admin", "root"}
page.sysauth = "Admin"
请指点如何实现。
编辑:
感谢您的投入:
假设:应该存在第一个条目。例如:page.sysauth="Admin"
page.sysauth=______(空)时脚本失败。
这是我的工作脚本sysauth_adt.sh
#!/bin/bash
add () {
sed -i~ -e '28 { s/= "\(.*\)"/= {""}/; # Add curlies to a single entry.
s/}/,"'"$entry"'"}/ # Add the new entry.
}' "$file"
}
remove () {
sed -i~ -e '28 { s/"'"$entry"'"//; # Remove the entry.
s/,}/}/; # Remove the trailing comma (entry was last).
s/{,/{/; # Remove the leading comma (entry was first).
s/,,/,/; # Remove surplus comma (entry was inside).
s/{"\([^,]*\)"}/""/ # Remove curlies for single entry.
}' "$file"
}
if (( $# == 3 )) ; then
file=
action=
entry=
if [[ $action == add ]] ; then
if head -n28 | tail -n1 | grep -q ; then
echo 0
else
add
fi
elif [[ $action == remove ]] ; then
if head -n28 | tail -n1 | grep -q ; then
remove
else
echo 0
fi
fi
else
echo "Usage: ${0#*/} file (add | remove) entry" >&2
exit 1
fi
如果您的条目总是没有逗号的单个单词,您可以使用简单的 sed 脚本:
#!/bin/bash
add () {
sed -i~ -e '28 { s/= "\(.*\)"/= {""}/; # Add curlies to a single entry.
s/}/,"'"$entry"'"}/ # Add the new entry.
}' "$file"
}
remove () {
sed -i~ -e '28 { s/"'"$entry"'"//; # Remove the entry.
s/,}/}/; # Remove the trailing comma (entry was last).
s/{,/{/; # Remove the leading comma (entry was first).
s/,,/,/; # Remove surplus comma (entry was inside).
s/{"\([^,]*\)"}/""/ # Remove curlies for single entry.
}' "$file"
}
if (( $# == 3 )) ; then
file=
action=
entry=
if [[ $action == add ]] ; then
add
elif [[ $action == remove ]] ; then
remove
fi
else
echo "Usage: ${0#*/} file (add | remove) entry" >&2
exit 1
fi
脚本在添加或删除条目时不检查条目是否已存在于列表中。对于更复杂的任务,我可能会切换到真正的编程语言。
awk -F '[[:blank:]]+=[[:blank:]]+' '
# load every single entry
NR != 28 && FNR == NR && ~ /^page.sysauth$/ && [=10=] !~ /\{.*\}/ { aSysAdd[ ++SysAdd] = }
# load special line 28
NR == 28 {
gsub( /^{|}$/, "", Datas = )
SysOrg = split( Datas, aSysOrg, /[[:blank:]]*,[[:blank:]]*/)
}
# print standard lines
FNR != NR && !~ /^page.sysauth$/ { print }
# print line 28 (new version)
FNR != NR && FNR == 28 {
printf "page.sysauth = {" aSysOrg[ 1]
for( i = 2; i <= SysOrg; i++) printf ", %s", aSysOrg[ i]
for( i = 1; i <= SysAdd; i++) printf ", %s", aSysAdd[ i]
print "}"
# don't print other page.sysauth
}
' YourFile YourFile > YourFile.new
mv YourFile.new YourFile
使用 awk 进行 2 次读取(双 YourFile
不是错误且是必需的)
我是 shell 编程新手,必须完成以下任务。 我在第 28 行(静态)有一个包含以下行的文件。
page.sysauth = "Admin"
我想在每次创建 sysauth 的新条目时使用 shell 脚本替换这一行。
page.sysauth = {"Admin", "root"} page.sysauth = {"Admin", "root", "newAdmin"} 等等
我还想从这个 sysauth 变量中删除条目
page.sysauth = {"Admin", "root", "newAdmin"}
page.sysauth = {"Admin", "root"}
page.sysauth = "Admin"
请指点如何实现。
编辑: 感谢您的投入: 假设:应该存在第一个条目。例如:page.sysauth="Admin" page.sysauth=______(空)时脚本失败。
这是我的工作脚本sysauth_adt.sh
#!/bin/bash
add () {
sed -i~ -e '28 { s/= "\(.*\)"/= {""}/; # Add curlies to a single entry.
s/}/,"'"$entry"'"}/ # Add the new entry.
}' "$file"
}
remove () {
sed -i~ -e '28 { s/"'"$entry"'"//; # Remove the entry.
s/,}/}/; # Remove the trailing comma (entry was last).
s/{,/{/; # Remove the leading comma (entry was first).
s/,,/,/; # Remove surplus comma (entry was inside).
s/{"\([^,]*\)"}/""/ # Remove curlies for single entry.
}' "$file"
}
if (( $# == 3 )) ; then
file=
action=
entry=
if [[ $action == add ]] ; then
if head -n28 | tail -n1 | grep -q ; then
echo 0
else
add
fi
elif [[ $action == remove ]] ; then
if head -n28 | tail -n1 | grep -q ; then
remove
else
echo 0
fi
fi
else
echo "Usage: ${0#*/} file (add | remove) entry" >&2
exit 1
fi
如果您的条目总是没有逗号的单个单词,您可以使用简单的 sed 脚本:
#!/bin/bash
add () {
sed -i~ -e '28 { s/= "\(.*\)"/= {""}/; # Add curlies to a single entry.
s/}/,"'"$entry"'"}/ # Add the new entry.
}' "$file"
}
remove () {
sed -i~ -e '28 { s/"'"$entry"'"//; # Remove the entry.
s/,}/}/; # Remove the trailing comma (entry was last).
s/{,/{/; # Remove the leading comma (entry was first).
s/,,/,/; # Remove surplus comma (entry was inside).
s/{"\([^,]*\)"}/""/ # Remove curlies for single entry.
}' "$file"
}
if (( $# == 3 )) ; then
file=
action=
entry=
if [[ $action == add ]] ; then
add
elif [[ $action == remove ]] ; then
remove
fi
else
echo "Usage: ${0#*/} file (add | remove) entry" >&2
exit 1
fi
脚本在添加或删除条目时不检查条目是否已存在于列表中。对于更复杂的任务,我可能会切换到真正的编程语言。
awk -F '[[:blank:]]+=[[:blank:]]+' '
# load every single entry
NR != 28 && FNR == NR && ~ /^page.sysauth$/ && [=10=] !~ /\{.*\}/ { aSysAdd[ ++SysAdd] = }
# load special line 28
NR == 28 {
gsub( /^{|}$/, "", Datas = )
SysOrg = split( Datas, aSysOrg, /[[:blank:]]*,[[:blank:]]*/)
}
# print standard lines
FNR != NR && !~ /^page.sysauth$/ { print }
# print line 28 (new version)
FNR != NR && FNR == 28 {
printf "page.sysauth = {" aSysOrg[ 1]
for( i = 2; i <= SysOrg; i++) printf ", %s", aSysOrg[ i]
for( i = 1; i <= SysAdd; i++) printf ", %s", aSysAdd[ i]
print "}"
# don't print other page.sysauth
}
' YourFile YourFile > YourFile.new
mv YourFile.new YourFile
使用 awk 进行 2 次读取(双 YourFile
不是错误且是必需的)