正则表达式删除文件中以相同或定义字母结尾的行

时间:2011-09-20 18:28:29

标签: regex string macos bash sed

我需要以这种方式工作的 mac osx 的bash脚本:

./script.sh * folder/to/files/ 
#
# or #
#
./script.sh xx folder/to/files/

此脚本

  • 阅读文件列表
  • 打开每个文件并阅读每一行
  • 如果行以相同的字母(“ * ”模式)或自定义字母(“ xx ”)结束,则 删除行和重新保存文件
  • 备份原始文件

我的第一个做法是:

#!/bin/bash

# ck init params
if [ $# -le 0 ]
then
  echo "Usage: $0 <letters>"
  exit 0
fi

# list files in current dir
list=`ls BRUTE*` 
for i in $list 
do 

  # prepare regex    
  case $1 in
       "*") REGEXP="^.*(.)\1+$";;
       *) REGEXP="^.*[$1]$";;
  esac    
  FILE=$i

  # backup file
  cp $FILE $FILE.bak

  # removing line with same letters
  sed -Ee "s/$REGEXP//g" -i '' $FILE
  cat $FILE | grep -v "^$"

done

exit 0

但它并不像我想要的那样......

怎么了?
我该如何修复这个脚本?


实施例

$cat BRUTE02.dat BRUTE03.dat
aa
ab
ac
ad
ee
ef
ff
hhh
$

如果我使用' * ',我希望所有以相同字母结尾的文件都是干净的。
如果我使用' ff ',我希望所有以' ff '结尾的文件都是干净的。


啊,它在 Mac OSx 上。请记住,sed与传统的linux sed略有不同。

man sed

 sed [-Ealn] command [file ...]
 sed [-Ealn] [-e command] [-f command_file] [-i extension] [file
     

...

     

说明        sed实用程序读取指定的文件或标准输入   如果未指定文件,则按列表指定修改输入   命令。该        然后将输入写入标准输出。

 A single command may be specified as the first argument to sed. 
     

可以使用-e或-f选项指定多个命令。所有   命令已应用        按照指定的顺序输入到输入,而不管它们是什么   原点。

 The following options are available:

 -E      Interpret regular expressions as extended (modern)
     

正则表达式而不是基本正则表达式(BRE)。   re_format(7)手册页                完全描述了两种格式。

 -a      The files listed as parameters for the ``w'' functions
     默认情况下,在任何处理开始之前创建(或截断)

。   -a选项导致                sed延迟打开每个文件,直到包含的命令   相关的“w”函数应用于一行输入。

 -e command
         Append the editing commands specified by the command
     

命令列表的参数。

 -f command_file
         Append the editing commands found in the file
     

command_file到命令列表。编辑命令应该   每个都列在一个单独的行。

 -i extension
         Edit files in-place, saving backups with the specified
     

扩展。如果给出了零长度扩展,则不会进行备份   保存。这不是推荐                在就地时修补为零长度延伸   编辑文件,因为您可能会在某些情况下出现损坏或部分内容   磁盘空间在哪里                筋疲力尽等等。

 -l      Make output line buffered.

 -n      By default, each line of input is echoed to the standard
     在应用了所有命令后输出

。然后   选项抑制了这一点                行为。

 The form of a sed command is as follows:

       [address[,address]]function[arguments]

 Whitespace may be inserted before the first address and the
     

命令的功能部分。

 Normally, sed cyclically copies a line of input, not including
     

它的终止换行符,进入一个模式空间,(除非那里   是剩下的东西        在“D”函数之后,应用所有命令   选择该模式空间的地址,将模式空间复制到   标准输出,附加 -        换行,删除模式空间。

 Some of the functions use a hold space to save all or part of the
     

用于后续检索的模式空间。

其他什么?
这显然是我的问题?

感谢。

4 个答案:

答案 0 :(得分:1)

我不太了解bash shell所以我无法评估失败的原因 这只是对正则表达式的一种观察(这可能是错误的)。

*模式正则表达式看起来不错:
^.*(.)\1+$ that ended with same letters..

但文字模式可能不符合你的想法 当前:^.*[$1]$ that ended with 'literal string'
这不应该使用字符类。

将其更改为:^.*$1$

虽然$ 1(在进入正则表达式之前)中的字符串应该被转义 如果其中包含任何正则表达式元字符。

否则,你打算有一个角色类吗?

答案 1 :(得分:1)

perl -ne '
    BEGIN {$arg = shift; $re = $arg eq "*" ? qr/([[:alpha:]])\1$/ : qr/$arg$/}
    /$re/ && next || print
'

示例:

echo "aa
ab
ac
ad
ee
ef
ff" | perl -ne '
    BEGIN {$arg = shift; $re = $arg eq "*" ? qr/([[:alpha:]])\1$/ : qr/$arg$/}
    /$re/ && next || print
' '*'

产生

ab
ac
ad
ee
ef

答案 2 :(得分:1)

可能的问题:

  • 当您在命令行上放置*时,shell会将其替换为目录中所有文件的名称。您的$1永远不会等于*

还有一些提示:

  • 您可以替换replace:

此:

# list files in current dir
list=`ls BRUTE*` 
for i in $list 

使用:

for i in BRUTE*

此:

cat $ FILE | grep -v“^ $”

使用:

grep -v "^$" $FILE

除了可能出现的问题外,我看不到有什么东西在向我跳来跳去。你是什​​么意思 clean ?你能举例说明一个文件在之前和之后应该是什么样子以及命令会是什么样的吗?

答案 3 :(得分:0)

这就是问题!

grep '\(.\)\1[^\r\n]$' *
MAC OSX上的

( ) { }等......必须引用!!!

解决了,谢谢。