仅在必要时从文本文件中删除尾随空格

仅在必要时从文本文件中删除尾随空格

我正在使用删除尾随空格

sed -i 's/[ \t]*$//' *.txt

但是,此命令将重写所有文件。

有没有一种方便的方法来判断文本文件中是否有尾随空格并跳过那些没有尾随空格的?

答案1

您可以使用grepfirst 来查找是否有需要修改的行,尽管这在最坏的情况下仍然会读取文件两次(在只有最后一行需要修改的情况下):

for f in ./*.txt; do
    grep -q '[[:blank:]]$' "$f" &&
      sed -i 's/[[:blank:]]*$//' "$f"
done

答案2

一种方法可以如图find/grep/sed所示:

find . -maxdepth 1 -type f -name '*.txt' \
  -exec grep -q '[[:blank:]]$' {} \; \
  -exec sed -Ei -e 's/[[:blank:]]+$//' {} +
  • 如果 1 在当前目录中运行,则使用 -maxdepth 进行查找。
  • {} \; 指的是要传递到的文件的名称grep,并且\;正在转义 shell 元字符分号,该分号是命令结束符。我们逃避它,以便它到达-exec。你也可以将其写为';'
  • {} +{}现在已经知道了,这+意味着您传递了尽可能多的文件名sed(基本上,不是传递{}当前结果的单个文件名,而是在调用之前累积要用作参数find的列表)。这使我们能够最大限度地减少调用次数。{}sedsed

答案3

执行编辑,仅在存在差异时替换原始文件。

for file in *.txt
do
    sed 's/[ \t]*$//' < "$file" > "$file.tmp.$$" || continue
    cmp -s -- "$file" "$file.tmp.$$" ||
      cat < "$file.tmp.$$" > "$file" ||
      continue
    rm -f -- "$file.tmp.$$"
done

答案4

以下内容建立在罗艾玛的想法在所有文件上运行sed表达式,但只保留实际修改的文件。

它通过减少sed调用来修改这一点:

printf '%s\0' ./*.txt |
xargs -0 sed -i.bak 's/[[:blank:]]$//

然后,您可以浏览这些*.txt文件,将它们与原始文件进行比较,然后选择您想要保留的文件:

for name in ./*.txt; do
    if cmp -s "$name" "$name.bak"; then
        # keep original
        mv "$name.bak" "$name"
    else
        # keep modified
        rm "$name.bak"
    fi
done

或者,一次性完成这两项操作:

printf '%s\0' ./*.txt |
xargs -0 sh -c '
    sed -i.bak "s/[[:blank:]]$//" "$@"
    for name do
        if cmp -s "$name" "$name.bak"; then
            mv "$name.bak" "$name"
        else
            rm "$name.bak"
        fi
    done' sh

相关内容