2012-05-03 3 views
4

Я получил много файлов, имена которых, как это:извлечение числа из имен файлов

tmp1.csv 
tmp32.csv 
tmp9.csv 
tmp76.csv 
... 

Они находятся в той же директории, и я хочу, чтобы извлечь номера в имени файла. Как я могу это сделать в bash?

PS

Я попытался grep, но не может это сделать. Также я попробовал ${filename##[a-z]}. Правильно ли они идут?

ответ

3
for f in *.csv; do echo $f | egrep -o "[0-9]+" ; done 

Если у вас есть другой файл CSV с цифрами в именах файлов использовать:

for f in *.csv; do echo $f | sed -re 's/^tmp([0-9]+)\.csv$/\1/' ; done 
+0

Это правильный способ сделать это. – lukecampbell

+0

@lukecampbell Я не согласен с тем, что это канонически корректно - для grep нет необходимости, когда bash может выполнять внутреннее соответствие. Расширение параметра, соответствие регулярному выражению - все это встроено, никаких подпроцессов не требуется. Ничего плохого в этом ответе, но это не единственный правильный путь. –

+1

... на самом деле, я беру это обратно - в этом ответе много. запуск нового эха | Протокол grep для файла является злым. –

1
find . -maxdepth 1 -type f -name 'tmp[0-9]*.csv' | sed 's/tmp\([0-9]\+\).csv/\1/' 
+0

Awfully хрупок, учитывая, что он просто печатает имя любого другого файла CSV в неизмененной. –

+0

@CharlesDuffy Duly отметил. Обновлен мой ответ. Благодарю. –

3

я бы, вероятно, использовать пару заклятий из cut:

$ ls -1 *.csv | cut -dp -f 2 | cut -d. -f1 

Эта труба .:

  1. Показать все файлы, соответствующие модели *.csv, по одной в строке
  2. Используйте букву 'p' в качестве разделителя и вырежьте второе поле на каждой строке. Это трансформируетс, например, tmp4711.csv - 4711.csv.
  3. Используйте букву '.' как разделитель, и вырезать первое поле на каждой строке. Это преобразовывает 4711.csv в 4711, оставляя число изолированным, и все готово.
+0

Хрупкое, особенно в этом поведении, не определено с файлами, не соответствующими шаблону tmp ###. Csv. –

+0

Согласен; если вы собираетесь «вырезать -dp», вы должны хотя бы 'ls -1 tmp [0-9] *. csv', чтобы смягчить некоторые потенциальные ошибки. – ghoti

3

Easy Peasy, не используя подпроцессы или другие инструменты, внешние по отношению к колотить себя:

for f in *[0-9]*; do 
    if [[ $f =~ [0-9]+ ]] ; then 
    echo "$BASH_REMATCH" 
    fi 
done 
3
ls |grep -o "[0-9]\+" 

Пример:

$ ls *.csv 
3tmp44.csv newdata_write.csv tmp1.csv tmp2.csv 

$ ls *.csv |grep -o "[0-9]\+" 
3 
44 
1 
2 

Edit:

От человека странице Grep:

Basic против расширенных регулярных выражений

In basic regular expressions the meta-characters ?, +, {, |, (, and) lose their special meaning; instead use the backslashed 
    versions \?, \+, \{, \|, \(, and \). 

Вот почему вы должны использовать \+

+0

2 вопроса. во-первых, что вы подразумеваете под 'только получите первое число? во-вторых, зачем бежать '+'? – Alcott

+0

@Alcott escape для '+' необходим в синтаксисе Basic RE (в отличие от синтаксиса ERE, который активируется 'egrep' или' grep -E', а не традиционным 'grep'). –

+0

Извините, я ошибся, он возвращает все числа. –

Смежные вопросы