2014-12-30 134 views
0

我试图放在一起bash脚本,将搜索一堆文件,如果它发现一个文件中的特定字符串,它会在该行后添加一个新行然后转到下一个文件。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它将陷入循环,直到磁盘填满。

有什么建议吗?

+1

然后就重定向到一个临时文件,然后将其移动到您的原始文件。另外,我猜你的代码可以使用正确的工具减少很多。一个'find'和'awk'应该或多或少够用,而你使用很多不同的东西。 – fedorqui

回答

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

如果你可以,也许使用临时文件?

~$ 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

最好使用'awk'...'file> tmp && mv tmp file',就像user00 ... 0001一样。在'awk'失败的情况下,'&&'技巧可以防止在输出错误的情况下覆盖'file'。 – fedorqui

+0

@fedorqui注意到 – fredtantini

+1

谢谢,我用sed选项。我发现我的循环也有问题,但sed方法允许我发现它。 – vmos

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) 
相关问题