bash:String具有正则表达式的运算符

时间:2014-02-18 04:13:21

标签: regex linux bash shell terminal

我想列出home文件夹中的所有文件,然后删除文件名中的#。 例如: #.emacs#应打印为.emacs

这是我的代码

for dir in $(ls ~)
do
    # trim trailing
    filename="${dir#\#}"
    echo ${filename}
done

但它仍在显示#之前的文件,尽管我在终端中管理了正则表达式${dir#\#}

你能告诉我代码中的气味在哪里吗?

5 个答案:

答案 0 :(得分:3)

从文件名中删除#,应为:

filename="${dir//#/}"

编辑:在某些系统(如Solaris)中,上面的命令不起作用,需要转义。

filename="${dir//\#/}"

其余的对于cygwin和Solaris都很好。

如果您需要在#

之前删除所有内容
filename="${dir##*#}"

如果您需要在#

之后删除所有内容
filename="${dir%%#*}"

以下是我从bash Substring Replacement

复制和粘贴的完整说明
${string/substring/replacement}
Replace first match of $substring with $replacement.

${string//substring/replacement}
Replace all matches of $substring with $replacement.

${string%substring}
Deletes shortest match of $substring from back of $string.

${string%%substring}
Deletes longest match of $substring from back of $string.

${string#substring}
Deletes shortest match of $substring from front of $string.

${string##substring}
Deletes longest match of $substring from front of $string.

答案 1 :(得分:1)

Don't parse ls。您可以只改为通配符扩展。此外,您使用参数扩展是错误的,${word#something}从前缀而不是后缀中删除something。所以试试

#!/bin/bash
for dir in ~/*
do
  # trim trailing
  filename="${dir%#}"
  echo "${filename}"
done

答案 2 :(得分:1)

嗨,您只需echo文件名,但不能重命名。首先,您需要从脚本cdhome目录,然后重命名文件。请在脚本下方查找包含#字符的文件名,并从文件名中删除#

#! /bin/bash
cd ~
for i in $(ls ~ )
do 
 if [[ "${i}" == *#* ]]
 then
    var=$(echo "$i" | sed 's/#//' )
    printf "%s\n" "$var" #to print only
    #mv  "$i" "$var" #to renmae
 fi
done

答案 3 :(得分:1)

这是一个 - 希望 - 有启发性的版本:

#!/usr/bin/env bash

# Make pathname expansion match files that start with '.', too.
shopt -s dotglob

# Loop over all files/dirs. in the home folder.
for f in ~/*; do
  # Exit, if no files/dirs match at all (this test may 
  # not be necessary if `shopt -s nullglob` is in effect).
  # Use -f to only match files, -d to only match dirs.
  [[ -e $f ]] || break
  # Remove the path component ... 
  filename=$(basename "$f")
  # ... and then all '#' chars. from the name.
  filename="${filename//#/}"
  # Process result
  echo "${filename}"
done
  • 正如其他人所说,你不应该解析ls输出 - 直接路径名扩展globs(通配符模式)总是更好的选择。
  • shopt -s dotglob可确保名称以.开头的文件或目录包含在路径名扩展中。
  • 路径名扩展在路径组件完整的情况下发生,因此要从循环变量中获取纯文件名,必须应用basename(第一个),以便去除路径组件。
  • 这里可能不是问题,但除非shopt -s nullglob生效(默认情况下不是这样),否则不匹配的glob将保持不变,因此输入的循环文件无效 - 因此{{1} } test。

答案 4 :(得分:0)

您之前没有声明文件在文件名的开头末尾有#。尝试类似:

for dir in ~/*; do 
    filename="${dir#\#}"
    filename="${filename%\#}"
    echo "$dir ---> ${filename}"
done

或使用BMW显示的第一个例子:

for dir in ~/*; do 
    filename="${dir//#/}"
    echo "$dir ---> ${filename}"
done

echo的输出感到满意。您可以将其替换为mv

P.S:重复BroSlow所述的内容。 Don’t parse ls.