Shell脚本-如果不存在某些文本,则读取文件并添加行



更新:感谢大家的投入。我相信我正在努力实现的目标有点混乱。我已经在下面的编辑中解决了这些问题。

原始问题:

当涉及到shell脚本时,我是一个傻瓜,我会尽力想出自己的脚本。下面的代码经过了多次迭代才达到这一点。

很抱歉,如果答案是,我无法满足我的需求,因此产生了这个问题。

场景:IP电话设置服务器。一个文件夹包含多个文件夹,其中大多数是.cfg文件。其中,如果文件名以001565或805ec0开头,则添加一行"sip.listen_port"。忽略其他所有内容。

问题:我能够做到以上没有任何问题。然而缺点是,如果文件已经有这一行,我的脚本会添加另一行。

预期结果:我想做的是,阅读文件,看看文本是否存在,然后添加行。这就是我失败的地方。

如果能为我指明正确的方向,我们将不胜感激。

当前代码:

#!/bin/bash
#check old yealink phones are there
if ls 001565* 1> /dev/null 2>&1; then
LOOP=0
FILES=001565*
else
LOOP=1
FILES=805ec0*
fi
while [ $LOOP -lt 2 ]; do
for f in $FILES
do
while read -r line; do
if [[ "$line" =~ "sip.listen_port*" ]]; then                
UNAME=$(awk '/user_name/{print $NF}' "$f")
# take action on each file. $f store current file name
# check the lenght of extension number and set the 
if [ ${#UNAME} -lt 2 ]; then
echo "sip.listen_port = 900$UNAME" >> $f
elif [ ${#UNAME} -lt 3 ]; then
echo "sip.listen_port = 90$UNAME" >> $f
elif [ ${#UNAME} -lt 4 ]; then
echo "sip.listen_port = 9$UNAME" >> $f
else
UNAME=${UNAME:(-3)}
echo "sip.listen_port = 9$UNAME" >> $f
fi
fi
done < "$f"
done
#check new yealink phones are there
if ls 805ec0* 1> /dev/null 2>&1; then
FILES=805ec0*
LOOP=$((LOOP+1))
else
LOOP=$((LOOP+2))
fi
done

编辑1:为了消除混乱,让我添加一张图片,展示典型文件夹中的文件以及典型文件的内容。

文件夹结构

典型文件内容:

#!version:1.0.0.1
## the file header "#!version:1.0.0.1" can not be edited or deleted. ##
account.1.auth_name = 105
account.1.display_name = 105
account.1.enable = 1
account.1.label = 105
account.1.password = 
account.1.sip_server.1.address = pbx.dns.name
account.1.sip_server.2.address = 
account.1.user_name = 105
auto_provision.server.url = http://provisioning.url/

工作原理:脚本将检查当前文件夹,每个文件以001565或805ec0开头,并添加以下行。

sip.listen_port = 9XXX

我试图实现的是,如果上面的行存在,就不应该对文件进行任何修改。

希望这有助于澄清任何问题。

无需使用while ... done < "$f"读取所有行。您可以使用简单的grep来代替:

for ...  
if ! grep -q '^[[:blank:]]*sip.listen_port' "$f"; then 
...
...
echo "sip.listen_port = something" >> "$f"
fi
done

如果您坚持使用while,您可以尝试以下操作:

for ...
found=0
while IFS= read -r line; do
[[ $line =~ ^[[:blank:]]*"sip.listen_port" ]] && { found=1; break;}
done < "$f"
if ! ((found)); then
...
...
echo "sip.listen_port = something" >> "$f"
fi
done

查看您的代码,我有一种感觉,如果您的文件包含"sip.listen_port",它会添加额外的一行,但如果该行不存在,则不会添加。我是对的?如果是这样的话,那么你只需要颠倒条件:

if [[ ! ("$line" =~ "sip.listen_port*") ]]; then

如果我理解正确:

$ ll                      
total 4,0K
-rw------- 1 vkd vkd  0 июл 16 10:03 001565tmp.2rbFa0rT3G
-rw------- 1 vkd vkd  0 июл 16 10:03 001565tmp.6o5BywVcLF
-rw------- 1 vkd vkd  0 июл 16 10:03 805ec0tmp.220Jgcmv0e
-rw------- 1 vkd vkd  0 июл 16 10:03 805ec0tmp.7EGpvDw71e
-rw------- 1 vkd vkd 28 июл 16 10:03 805ec0tmp.F78rxzUBCz
$ cat *
sip.listen_port = something # only file 805ec0tmp.F78rxzUBCz has this entry

脚本:

#!/usr/bin/env bash
FILES_DIR=<your_path>
for filename in `ls $FILES_DIR | grep -E "^(001565|805ec0)"`
do
if grep -q '^sip.listen_port = something' $filename
then
continue
else
echo "sip.listen_port = something" >> $filename
fi
done

结果:

$ ll
total 20K
-rw------- 1 vkd vkd 28 июл 16 10:03 001565tmp.2rbFa0rT3G
-rw------- 1 vkd vkd 28 июл 16 10:03 001565tmp.6o5BywVcLF
-rw------- 1 vkd vkd 28 июл 16 10:03 805ec0tmp.220Jgcmv0e
-rw------- 1 vkd vkd 28 июл 16 10:03 805ec0tmp.7EGpvDw71e
-rw------- 1 vkd vkd 28 июл 16 10:03 805ec0tmp.F78rxzUBCz
$ cat *       
sip.listen_port = something
sip.listen_port = something
sip.listen_port = something
sip.listen_port = something
sip.listen_port = something

第页。S: 我没有理解UNAME的逻辑。。。你的输出并不能解释这个var是什么,所以我决定它将是"某种">

UPD:

#!/usr/bin/env bash
FILES_DIR="<your_path>"
for filename in `ls $FILES_DIR | grep -E "^(001565|805ec0)"`
do
if grep -qE '^sip.listen_port = [0-9]+' $filename
then
continue
else
uname=`awk '/^account.1.user_name = [0-9]+/ {print $3}' $filename`
echo "sip.listen_port = 9$uname" >> $filename
fi
done

之前:

$ ll
total 16K
-rw------- 1 vkd vkd 26 июл 16 16:36 001565tmp.2rbFa0rT3G
-rw------- 1 vkd vkd 53 июл 16 16:36 001565tmp.6o5BywVcLF
-rw------- 1 vkd vkd 28 июл 16 16:35 805ec0tmp.5ai0gFOkas
-rw------- 1 vkd vkd 25 июл 16 16:35 805ec0tmp.F78rxzUBCz
$ cat 001565tmp.2rbFa0rT3G 
account.1.user_name = 105
$ cat 001565tmp.6o5BywVcLF 
account.1.user_name = 21516
sip.listen_port = 921516
$ cat 805ec0tmp*          
account.1.user_name = 12345
account.1.user_name = 18

之后:

$ cat 001565tmp.*
account.1.user_name = 105
sip.listen_port = 9105
account.1.user_name = 21516
sip.listen_port = 921516
$ cat 805ec0tmp.*
account.1.user_name = 12345
sip.listen_port = 912345
account.1.user_name = 18
sip.listen_port = 918

最新更新