Regex 行为不端?

Regex 行为不端?,regex,bash,sed,Regex,Bash,Sed,我有以下命令: $ xlscat -i $file 我得到: Excel File Name.xslx - 01: [ Sheet #1 ] 34 Cols, 433 Rows Excel File Name.xlsx - 02: [ Sheet Number2 ] 23 Cols, 32 Rows Excel File Name.xlsx - 03: [ Foo Factor! ] 14 Cols, 123 Rows 我只需要工作表名称,因此我执行以

我有以下命令:

$ xlscat -i $file
我得到:

Excel File Name.xslx - 01:  [ Sheet #1      ] 34 Cols,    433 Rows
Excel File Name.xlsx - 02:  [ Sheet Number2 ] 23 Cols,     32 Rows
Excel File Name.xlsx - 03:  [ Foo Factor!   ] 14 Cols,    123 Rows
我只需要工作表名称,因此我执行以下操作:

$ xlscat -i $file 2>&1 | sed -e 's/.*\[  *\(.*\)  *\].*/\1/' | while read file
> do
>    echo "File: '$file'"
> done
得到这个:

File: 'Sheet #1'
File: 'Sheet Number2'
File: 'Foo Factor!'
File: 'Sheet_#1_____'
File: 'Sheet_Number2'
File: 'Foo_Factor!__'
太好了!一切都很好。如单引号所示,我删除了文件名末尾的多余空格。现在将所有剩余的空格转换为下划线:

$ xlscat -i $file 2>&1 | sed -e 's/.*\[  *\(.*\)  *\].*/\1/' | sed -e 's/ /_/g' |  while read file
> do
>    echo "File: '$file'"
> done
现在我明白了:

File: 'Sheet #1'
File: 'Sheet Number2'
File: 'Foo Factor!'
File: 'Sheet_#1_____'
File: 'Sheet_Number2'
File: 'Foo_Factor!__'

嗯?第一个文件没有显示任何尾随空格,但第二个文件似乎在文件末尾添加了下划线。我没有看到什么

我认为
读取文件
正在为您修剪尾部空白。试着把

sed -e 's/ /_/g'
在while循环中。。。比如:

echo "File: $(echo $file | sed -e 's/ /_/g')"

我认为
读取文件
正在为您修剪尾部空白。试着把

sed -e 's/ /_/g'
在while循环中。。。比如:

echo "File: $(echo $file | sed -e 's/ /_/g')"

是不是
echo
在剥离尾随空格?虽然看起来他们应该出现在引号里。无论如何,试试这个:

sed -e 's/.*\[ *\([^] ]\+\( \+[^] ]\+\)*\).*/\1/'
工作表名称的每个单词都由
[^]]\+
匹配(即,空格或
]
以外的一个或多个字符)。当名称的最后一个单词已匹配时,第二个
*
将占用该行的其余部分。无需匹配结束符
]
,因此匹配中不必包含尾随空格


我不是
sed
用户,但是当我指定GNU-BRE风格时,这个正则表达式在RegexBuddy中工作正常,所以它应该在
sed

中工作,是否是
echo
在剥离尾随空格?虽然看起来他们应该出现在引号里。无论如何,试试这个:

sed -e 's/.*\[ *\([^] ]\+\( \+[^] ]\+\)*\).*/\1/'
工作表名称的每个单词都由
[^]]\+
匹配(即,空格或
]
以外的一个或多个字符)。当名称的最后一个单词已匹配时,第二个
*
将占用该行的其余部分。无需匹配结束符
]
,因此匹配中不必包含尾随空格


我不是
sed
用户,但是当我指定GNU-BRE风格时,这个正则表达式在RegexBuddy中工作正常,因此它应该在
sed
中工作。第一个
sed
命令不是去除尾部空白,而是
read
命令。检查您的表情:

 sed -e 's/.*\[  *\(.*\)  *\].*/\1/'
它匹配:

  • 任何事
  • 括号
  • 1个或多个空间
  • 什么都可以,俘虏了吗
  • 1个或多个空间
  • 右括号
  • 任何事
  • 正则表达式是贪婪的,这意味着它们尽可能多地匹配,而前面的表达式将在后面的表达式匹配之前匹配。例如,正则表达式
    (.*)(.*)
    匹配两个捕获组中的任何内容,但是有多种方法可以在两个组之间分割数据。因此regex实现必须选择,它将尽可能多地放在第一个中,而在第二个中什么也不放

    由于需要将文件名与其中的空格相匹配,因此不能匹配“除空格外的任何内容”;最好的办法是将尾部空白作为单独的步骤进行修剪。请改为尝试此sed命令:

    sed -e 's/.*\[  *\(.*\)  *\].*/\1/' -e 's/ *$//'
    

    第一个
    sed
    命令不是去除尾随空格,
    read
    是。检查您的表情:

     sed -e 's/.*\[  *\(.*\)  *\].*/\1/'
    
    它匹配:

  • 任何事
  • 括号
  • 1个或多个空间
  • 什么都可以,俘虏了吗
  • 1个或多个空间
  • 右括号
  • 任何事
  • 正则表达式是贪婪的,这意味着它们尽可能多地匹配,而前面的表达式将在后面的表达式匹配之前匹配。例如,正则表达式
    (.*)(.*)
    匹配两个捕获组中的任何内容,但是有多种方法可以在两个组之间分割数据。因此regex实现必须选择,它将尽可能多地放在第一个中,而在第二个中什么也不放

    由于需要将文件名与其中的空格相匹配,因此不能匹配“除空格外的任何内容”;最好的办法是将尾部空白作为单独的步骤进行修剪。请改为尝试此sed命令:

    sed -e 's/.*\[  *\(.*\)  *\].*/\1/' -e 's/ *$//'
    

    它确实会修剪空格并将空格序列转换为单个空格,如果需要,可以将其转换为
    IFS=read file
    。谢谢,但它仍然没有回答我的问题:为什么第一个示例显示尾部空格被删除,而第二个示例,第二个
    sed
    命令似乎实际看到了先前删除的空格。最初,它是一个带有两个
    -e
    参数的
    sed
    命令,但在看到结果后,我认为这两个替换可能同时发生。然而,pip应该已经解决了这个问题。我一定错过了什么明显的东西。什么事?@DavidW。第一个示例没有显示
    sed
    删除了尾随空格(请参阅evil otto的答案,了解更多有关sed与空白匹配的原因的详细信息)。第一个示例只是显示,在运行
    echo
    时,空白已经消失。(它是
    read
    吃空格。)在第二个例子中,在
    read
    运行之前,空格被替换为下划线,因此
    read
    没有空格可吃。第一个
    sed
    命令从来没有去掉尾随空格,
    read
    就是这样做的(参见@evil otto的答案)。在第二个版本中,在read看到尾随空格之前,尾随空格被转换为“u”,因此它们从未被剥离。它确实会修剪空格并将空格序列转换为单个空格,如果需要,可以将其转换为
    IFS=read file
    。谢谢,但它仍然没有回答我的问题:为什么第一个示例显示尾部空格被删除,而第二个示例显示第二个
    sed
    命令实际看到了先前删除的空格。最初,它是一个带有两个
    -esed
    命令