我有一个简单的shell脚本,可以从文件中删除尾随空格。有没有办法使这个脚本更加紧凑(不创建临时文件)?
sed 's/[ \t]*$//' $1 > $1__.tmp
cat $1__.tmp > $1
rm $1__.tmp
我有一个简单的shell脚本,可以从文件中删除尾随空格。有没有办法使这个脚本更加紧凑(不创建临时文件)?
sed 's/[ \t]*$//' $1 > $1__.tmp
cat $1__.tmp > $1
rm $1__.tmp
您可以在Linux和Unix中使用sed
的就地选项-i
:
sed -i 's/[ \t]*$//' "$1"
请注意,该表达式将在OSX上删除尾随的t
(您可以使用gsed
来避免此问题)。它也可能会在BSD上删除它们。
如果您没有gsed,在OSX上这里是正确的(但难以阅读的)sed语法:
sed -i '' -E 's/[ '$'\t'']+$//' "$1"
$'\t'
解析为一个字面制表符(使用ANSI-C quoting),因此制表符被正确地连接到表达式中。sed: 未识别的标记:i
。 - javaPlease42t
了 :) \t
表示制表符,对于那些可能还不知道的人来说。 - Sean Allred至少在Mountain Lion上,Viktor的答案也会在行尾出现字符“t”时将其删除。以下修复此问题:
sed -i '' -e's/[[:space:]]*$//' "$1"
-E
,表示“扩展(现代)正则表达式”。 - Jared Becksed
没有出现问题。 - Franklin Yu|sed -r -e 's"^[[:space:]]*""' -e 's"[[:space:]]*$""'
"` - Aquarius Power感谢codaddict提出的-i
选项。
以下命令可解决Snow Leopard上的问题。
sed -i '' -e's/[ \t]*$//' "$1"
\t
,因为它会被解释为字母 t
。这个命令似乎只能工作,可能是因为文件中没有制表符或句子结尾处没有字母 t
。建议不要在未指定备份后缀的情况下使用 ''
。 - Scrutinizer最好也引用$1:
sed -i.bak 's/[[:blank:]]*$//' "$1"
我有一个脚本放在我的.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
}
var1="\t\t Test String trimming "
echo $var1
Var2=$(echo "${var1}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo $Var2
对于那些寻求效率的人(需要处理许多文件或大文件),使用+
重复操作符而不是*
可以使命令速度提高两倍以上。
使用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
ls | xargs sed -i 's/[ \t]*$//'
echo test | sed 's/[ \t]*$//'
会被截断为tes
。 - undefined这些答案让我感到困惑。这两个sed
命令在Java源文件上都能够正常执行:
sed 's/\s\+$/ 文件名
sed 's/[[:space:]]\+$// 文件名
为了测试目的,我使用了:
$ echo " abc " | sed 's/\s\+$/-xx/'
abc-xx
$ echo -e " abc \t\t " | sed 's/\s\+$/-xx/'
abc-xx
将所有尾随的空格替换为"-xx
"。
@Viktor希望避免使用临时文件,个人建议只使用-i
=> 带有备份后缀的原地操作。至少在我确定命令可行之前是这样的。
抱歉,我觉得现有的回答有点含糊不清。sed
是一个直截了当的工具。90%的时间里,以一种直截了当的方式来处理它会更容易。或者我可能错过了什么,很高兴在那里得到纠正。
mv
代替cat
和rm
。你为什么要那样使用cat
呢?为什么不使用cp
呢? - Dennis Williamsoncat
覆盖原始文件而不是mv
实际上会替换原始文件中的数据(即,它不会破坏硬链接)。使用许多解决方案中提出的sed -i
也不会这样做。换句话说,继续做你正在做的事情。 - William Pursell