bash,在一行之后添加字符串

时间:2014-12-30 14:41:15

标签: bash loops awk sed

我试图整理一个搜索一堆文件的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它会被卡住在循环中直到磁盘填满。

有什么建议吗?

3 个答案:

答案 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)