2015-03-26 3 views
0

Я знаю, что подобные вещи были заданы раньше, но я не смог действительно сделать руку и ногу из того, что было опубликовано.Извлечение даты из имени файла с использованием сценария bash

У меня есть целая куча файлов, которые содержат дату в формате YYYYMMDD в какой-то момент в имени файла. К счастью, это единственная 8-значная подстрока во всех именах файлов!

Мне нужно будет записать даты в другой файл позже, но это должно быть хорошо. Я изо всех сил, чтобы извлечь дату в переменную первого ...

Я знаю, что могу получить его с Grep:

for d in $(ls *.csv | grep -Po "\d{8}"; do 
echo $d done 

Однако, как я хочу, чтобы получить полное имя файла в переменную тоже пока Я повторяю их, это не вариант сейчас.

Я попытался с помощью СЭД, но я не думаю, что я знаю, как использовать его:

for f in $(ls *.csv); do 
    d=$($f | sed -e 's/^.*\(\d{8}\).*$') 
    echo $d 
done 

Спасибо за указание мне в правильном направлении!

+0

Не могли бы вы разместить несколько примеров имен файлов? –

+0

Здесь вообще не нужно 'sed'; bash может выполнять регулярное выражение, соответствующее изначально. –

+0

... также см. Http://mywiki.wooledge.org/ParsingLs –

ответ

1
#!/bin/bash 
#  ^-- important: bash, not not /bin/sh 

for f in *.csv; do      # Don't use ls for iterating over filenames 
    [[ $f =~ [[:digit:]]{8} ]] && {  # native built-in regex matching 
    number=${BASH_REMATCH[0]}   # ...refer to the matched content... 
    echo "Found $number in filename $f" # ...and emit output. 
    } 
done 
+0

Я боюсь, что оба решения дают мне ошибку: something.sh: 19: something.sh: [[: не найдено – dengar81

+1

@ dengar81, это означает, что ваша оболочка не bash; вы отметили свой вопрос 'bash', а не' sh', поэтому используйте bash как свою оболочку: запустите свой скрипт с помощью '#!/bin/bash', а не' #!/bin/sh' - и, при запуске на prompt, 'bash yourscript', а не' sh yourscript'. –

2

Loop через ваши файлы CSV, как это (не разобрать ls):

for f in *.csv; do 
    echo "$f" 
    d=$(echo "$f" | grep -oE '[0-9]{8}') 
done 

Я использовал Grep в расширенном режиме (-E), но PERL режиме равноценны.

Как вы отметили , вы можете сделать d=$(grep -oE '[0-9]{8}' <<<"$f", если хотите. Вы также можете использовать встроенные в поддержку регулярных выражений, что немного более многословным, но сохраняет вызов внешнего инструмента:

re='[0-9]{8}' 
[[ $f =~ $re ]] && d="${BASH_REMATCH[0]}" 

Массив BASH_REMATCH содержит совпадение регулярного выражения. Если есть совпадение, мы назначаем его d.

+0

Назначение регулярного выражения переменной перед использованием '= ~' - как вы это делаете - это, безусловно, лучшая практика для тех, кто нуждается в совместимости с более старые версии bash. Вы помните, какие релизы там, где это имеет значение? Моя память говорит мне, что это 3,0-эра, но я не уверен, насколько я ей доверяю. –

+0

@Charles Я не уверен в деталях, если честно, я всегда делаю это так, потому что мудрый человек по имени Грег сказал мне, - здесь обсуждается разница между версиями: http: //mywiki.wooledge. org/BashGuide/Patterns # Regular_Expressions –

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