Сед плохое поведение? - PullRequest
       5

Сед плохое поведение?

1 голос
/ 26 октября 2011

У меня есть следующая команда:

$ 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!'

Отлично! Все работает красиво. Как вы можете видеть из одинарных кавычек, я удалил лишние пробелы в конце имени файла. Теперь преобразуйте все оставшиеся пробелы в подчеркивание:

$ 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!__'

А? Первый не показывал никаких пробелов, но второй, кажется, добавляет подчеркивание в конце файла. Что я не вижу?

Ответы [ 3 ]

4 голосов
/ 26 октября 2011

Первая команда sed не удаляет конечные пробелы, read. Проверьте свое выражение:

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

Соответствует:

  1. ничего
  2. скобка
  3. 1 или более пробелов
  4. все, что захвачено
  5. 1 или более пробелов
  6. правая скобка
  7. ничего

Регулярные выражения являются жадными, что означает, что они совпадают настолько, насколько это возможно, и более ранние выражения будут совпадать раньше, чем более поздние. Так, например, регулярное выражение (.*)(.*) соответствует чему-либо в двух группах захвата, но существует несколько способов разделения данных между двумя группами. Таким образом, реализация regex должна выбирать, и она поместит как можно больше в первое, а ничего во второе.

Поскольку вам нужно сопоставлять имена файлов с пробелами в них, вы не можете сопоставить «что угодно, кроме пробела»; Лучше всего обрезать завершающие пробелы в качестве отдельного шага. Попробуйте вместо этого команду sed:

sed -e 's/.*\[  *\(.*\)  *\].*/\1/' -e 's/ *$//'
4 голосов
/ 26 октября 2011

Я думаю, что read file урезает пробел для вас. Попробуйте поставить

sed -e 's/ /_/g'

внутри цикла while ... вроде:

echo "File: $(echo $file | sed -e 's/ /_/g')"
0 голосов
/ 26 октября 2011

Может ли это быть echo, что убирает пробелы?Хотя кажется, что они должны появляться в кавычкахВ любом случае попробуйте следующее:

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

Каждое слово имени листа соответствует [^] ]\+ (т. Е. Один или несколько любых символов, отличных от пробела или ]).Когда последнее слово в имени совпадает, второе .* занимает остаток строки.Нет необходимости совпадать с закрывающим ], поэтому не нужно включать конечные пробелы в совпадении.

Я не пользователь sed, но это регулярное выражение работает правильно в RegexBuddy, когдаЯ указываю разновидность GNU-BRE, поэтому она должна работать в sed.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...