我试图整理一个搜索一堆文件的bash脚本,如果它在文件中找到一个特定的字符串,它会在该字符串之后的行上添加一个新行,然后继续下一个文件。
#! /bin/bash
echo "Creating variables"
SEARCHDIR=testfile
LINENUM=1
find $SEARCHDIR* -type f -name *.xml | while read i; do
echo "Checking $i"
ISBE=`cat $i | grep STRING_TO_SEARCH_FOR`
if [[ $ISBE =~ "STRING_TO_SEARCH_FOR" ]] ; then
echo "found $i"
cat $i | while read LINE; do
((LINENUM=LINENUM+1))
if [[ $LINE == "<STRING_TO_SEARCH_FOR>" ]] ; then
echo "editing $i"
awk -v "n=$LINENUM" -v "s=new line to insert" '(NR==n) { print s } 1' $i
fi
done
fi
LINENUM=1
done
我遇到问题的是
awk -v "n=$LINENUM" -v "s=new line to insert" '(NR==n) { print s } 1' $i
如果我最后只使用$ i,它会将内容输出到屏幕,如果我使用$i > $i
那么它只会删除文件,如果我使用$i >> $i
它会被卡住在循环中直到磁盘填满。
有什么建议吗?
答案 0 :(得分:1)
不幸的是,awk没有使用就地替换选项,类似于sed的-i
,因此您可以创建一个临时文件,然后将其删除:
awk '{commands}' file > tmpfile && mv tmpfile file
如果您有GNU awk 4.1.0 or newer,则会添加-i inplace
,您可以这样做:
awk -i inplace '{commands}' file
修改原始
答案 1 :(得分:1)
如果可以,可以使用临时文件吗?
~$ awk ... $i > tmpfile
~$ mv tmpfile $i
或只是awk ... $i > tmpfile && mv tmpfile $i
请注意,您可以使用mktemp
创建此临时文件。
否则,使用sed,您可以在匹配后立即插入一行:
~$ cat f
auie
nrst
abcd
efgh
1234
~$ sed '/abcd/{a\
new_line
}' f
auie
nrst
abcd
new_line
efgh
1234
命令搜索该行是否与/abcd/
匹配,如果是,则会追加(a\
)行new_line
。
自从sed
作为替换内联的-i
以来,您可以这样做:
if [[ $ISBE =~ "STRING_TO_SEARCH_FOR" ]] ; then
echo "found $i"
echo "editing $i"
sed -i "/STRING_TO_SEARCH_FOR/{a
\new line to insert
}" $i
fi
答案 2 :(得分:1)
#cat $i | while read LINE; do
# ((LINENUM=LINENUM+1))
# if [[ $LINE == "<STRING_TO_SEARCH_FOR>" ]] ; then
# echo "editing $i"
# awk -v "n=$LINENUM" -v "s=new line to insert" '(NR==n) { print s } 1' $i
# fi
# done
# replaced by
sed -i 's/STRING_TO_SEARCH_FOR/&\n/g' ${i}
或使用awk代替sed
也
# ISBE=`cat $i | grep STRING_TO_SEARCH_FOR`
# if [[ $ISBE =~ "STRING_TO_SEARCH_FOR" ]] ; then
#by
if [ $( grep -c 'STRING_TO_SEARCH_FOR' ${i} ) -gt 0 ]; then
# if file are huge, if not directly used sed on it, it will be faster (but no echo about finding the file)