我有一个简单的Shell脚本,可从文件中删除结尾的空格。有什么方法可以使此脚本更紧凑(无需创建临时文件)?
sed 's/[ \t]*$//' $1 > $1__.tmp
cat $1__.tmp > $1
rm $1__.tmp
cat
用于覆盖原始文件而不是mv
实际替换原始文件中的数据(即,它不会破坏硬链接)。sed -i
如许多解决方案中所建议的那样使用将无法做到这一点。IOW,继续做您正在做的事情。
我有一个简单的Shell脚本,可从文件中删除结尾的空格。有什么方法可以使此脚本更紧凑(无需创建临时文件)?
sed 's/[ \t]*$//' $1 > $1__.tmp
cat $1__.tmp > $1
rm $1__.tmp
cat
用于覆盖原始文件而不是mv
实际替换原始文件中的数据(即,它不会破坏硬链接)。sed -i
如许多解决方案中所建议的那样使用将无法做到这一点。IOW,继续做您正在做的事情。
Answers:
您可以选择的地方使用-i
的sed
Linux和Unix:
sed -i 's/[ \t]*$//' "$1"
请注意,该表达式将删除t
OSX上的尾随(您可以使用它gsed
来避免此问题)。它也可能在BSD上将其删除。
如果没有ged,则OSX上的sed语法正确(但难于理解):
sed -i '' -E 's/[ '$'\t'']+$//' "$1"
最终,三个单引号的字符串被连接成单个参数/表达式。bash中没有串联运算符,您只需将字符串一个接一个地放置,并且它们之间没有空格。
的$'\t'
解析为在bash字面制表符(使用ANSI-C引用),所以标签被正确地连接成的表达。
sed: Not a recognized flag: i
t
:) \t
是一个选项卡。
感谢codaddict建议该-i
选项。
以下命令解决了雪豹上的问题
sed -i '' -e's/[ \t]*$//' "$1"
\t
除了GNU sed之外,您不能与sed一起使用,它会被解释为文字字母t
。该命令似乎只起作用,可能是因为尾随空白中没有TAB或t
文件中句子的末尾没有。使用''
不建议没有指定备份文件的后缀。
var1="\t\t Test String trimming "
echo $var1
Var2=$(echo "${var1}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo $Var2
我的.bashrc中有一个脚本,可在OSX和Linux下运行(仅限bash!)
function trim_trailing_space() {
if [[ $# -eq 0 ]]; then
echo "$FUNCNAME will trim (in place) trailing spaces in the given file (remove unwanted spaces at end of lines)"
echo "Usage :"
echo "$FUNCNAME file"
return
fi
local file=$1
unamestr=$(uname)
if [[ $unamestr == 'Darwin' ]]; then
#specific case for Mac OSX
sed -E -i '' 's/[[:space:]]*$//' $file
else
sed -i 's/[[:space:]]*$//' $file
fi
}
我添加到:
SRC_FILES_EXTENSIONS="js|ts|cpp|c|h|hpp|php|py|sh|cs|sql|json|ini|xml|conf"
function find_source_files() {
if [[ $# -eq 0 ]]; then
echo "$FUNCNAME will list sources files (having extensions $SRC_FILES_EXTENSIONS)"
echo "Usage :"
echo "$FUNCNAME folder"
return
fi
local folder=$1
unamestr=$(uname)
if [[ $unamestr == 'Darwin' ]]; then
#specific case for Mac OSX
find -E $folder -iregex '.*\.('$SRC_FILES_EXTENSIONS')'
else
#Rhahhh, lovely
local extensions_escaped=$(echo $SRC_FILES_EXTENSIONS | sed s/\|/\\\\\|/g)
#echo "extensions_escaped:$extensions_escaped"
find $folder -iregex '.*\.\('$extensions_escaped'\)$'
fi
}
function trim_trailing_space_all_source_files() {
for f in $(find_source_files .); do trim_trailing_space $f;done
}
对于那些追求效率的人(要处理的许多文件或大文件),使用+
重复运算符代替*
使命令快两倍以上。
使用GNU sed:
sed -Ei 's/[ \t]+$//' "$1"
sed -i 's/[ \t]\+$//' "$1" # The same without extended regex
我还很快对其他基准进行了基准测试:使用[ \t]
而不是[[:space:]]
可以大大加快过程(GNU sed v4.4):
sed -Ei 's/[ \t]+$//' "$1"
real 0m0,335s
user 0m0,133s
sys 0m0,193s
sed -Ei 's/[[:space:]]+$//' "$1"
real 0m0,838s
user 0m0,630s
sys 0m0,207s
sed -Ei 's/[ \t]*$//' "$1"
real 0m0,882s
user 0m0,657s
sys 0m0,227s
sed -Ei 's/[[:space:]]*$//' "$1"
real 0m1,711s
user 0m1,423s
sys 0m0,283s
纯娱乐:
#!/bin/bash
FILE=$1
if [[ -z $FILE ]]; then
echo "You must pass a filename -- exiting" >&2
exit 1
fi
if [[ ! -f $FILE ]]; then
echo "There is not file '$FILE' here -- exiting" >&2
exit 1
fi
BEFORE=`wc -c "$FILE" | cut --delimiter=' ' --fields=1`
# >>>>>>>>>>
sed -i.bak -e's/[ \t]*$//' "$FILE"
# <<<<<<<<<<
AFTER=`wc -c "$FILE" | cut --delimiter=' ' --fields=1`
if [[ $? != 0 ]]; then
echo "Some error occurred" >&2
else
echo "Filtered '$FILE' from $BEFORE characters to $AFTER characters"
fi
在的特定情况下sed
,-i
其他人已经提到的选择是最简单,最明智的选择。
在更普遍的情况下,sponge
从moreutils
收集,不正是你想要的东西:它可以让你替换文件,处理它的结果,在专为保持加工工序由覆盖十分文件,它是绊倒自己的方式正在努力。引用sponge
手册页:
海绵读取标准输入并将其写到指定文件中。与shell重定向不同,海绵在写入输出文件之前先吸收所有输入。这允许构造读取和写入同一文件的管道。
mv
代替cat
和rm
。你为什么要这样使用cat
?为什么不使用cp
?