在带有变量和正则表达式的for循环中使用sed

时间:2013-03-22 15:55:20

标签: bash for-loop sed

我正在尝试构建一个脚本,其中一部分内容使用了“sed'将文件名标记到该文件中每行的末尾,然后将输出转储到主列表。 脚本给我带来麻烦的部分在这里:

DIR=/var/www/flatuser
FILES=$DIR/*
for f in $FILES
do
    echo "processing $f file...."
    sed -i "s/$/:$f/" $f
    cat $f >> $DIR/master.txt
done

问题在于' sed'声明在for循环之外工作正常,但是当我把它放在脚本中时,我相信它有解释美元符号的问题。我已经尝试了几乎每一个"和'我可以想到让它来解释变量,它不断地放置" $ f"在每一行的末尾,或者它完全失败。

感谢您的任何意见!

4 个答案:

答案 0 :(得分:5)

你只需要逃脱美元符号:

sed -i "s/\$/:$f/" "$f"

以便shell将字面意思传递给sed

扩展Charles Duffy关于引用变量的观点:

DIR=/var/www/flatuser
for f in "$DIR"/*
do
    echo "processing $f file...."
    sed -i "s/\$/:${f##*/}/" "$f"
    cat "$f" >> "$DIR/master.txt"
done

如果任何文件名包含空格,如果将文件名列表分配给$FILES,则对它做任何事都为时已晚;您不能再区分属于文件名的空格和分隔文件名的空格。您可以使用数组,但将glob直接放入for循环更简单。以下是使用数组的方法:

DIR=/var/www/flatuser
FILES=( "$DIR"/* )
for f in "${FILES[@]}"
do
    echo "processing $f file...."
    sed -i "s/\$/:${f##*/}/" "$f"
    cat "$f" >> "$DIR/master.txt"
done

对于不使用sed的{​​{1}}版本,这里有一种显式处理模拟就地编辑所需的临时文件的方法:

-i

答案 1 :(得分:3)

就个人而言,我会这样做:

dir=/var/www/flatuser
for f in "$dir"/*; do
  [[ $f = */master.txt ]] && continue
  while read -r; do printf '%s:%s\n' "$REPLY" "${f##*/}"; done <"$f"
done >/var/www/flatuser/master.txt

它不会像sed -i那样就地修改您的文件,因此可以安全地运行多次(sed -i版本会将名称添加到您的文件中它运行的时间,所以你最终每行都有多个文件名副本。)

此外,POSIX未指定sed -i,因此并非所有操作系统都会拥有它。

答案 2 :(得分:0)

问题不在于美元符号。这是变量$ f包含一个“/”字符,而sed使用它来分隔表达式。尝试使用“@”作为分隔符。

DIR=/var/www/flatuser
FILES=$DIR/*
for f in $FILES
do
    echo "processing $f file...."
    sed -i s@"$"@:"$f"@ $f
    cat $f >> $DIR/master.txt
done

答案 3 :(得分:0)

它已经过时了,但也许对某人有所帮助。 为什么不将文件命名为摆脱前导目录

DIR=/var/www/flatuser
FILES=( "$DIR"/* )
for f in "${FILES[@]}"
do
    echo "processing $f file...."
    b=`basename $f`
    sed -i "s/\$/:${b##*/}/" "$b"
    cat "$f" >> "$DIR/master.txt"
done

未经测试......