Разбор строки с помощью оболочки

#linux #bash #shell

#linux #bash #оболочка

Вопрос:

Я хочу получить NetworkActivity_5851_*_09-04-2016.done строку из NetworkActivity_5851_2326316_09-04-2016.log.gz и вот код, который я написал

 local file="$1"
local extension="${file##*.}"
if [ $extension = 'done' ]; then
   local files=`basename $file`
   files="${files#*_}"
   files="${files#*_}"
   files="${files%_*}"
   local q=_"$files"_
   local mask="${file/done/log.gz}"
   mask="${mask/${q}/_*_}"
   r=`ls "${mask}" | wc -l`
  

и это работает правильно, но когда я запускаю его с помощью скрипта python, происходит сбой. Я имею в виду, что r переменная имеет неправильное значение.
Вот код на Python

     shell = Shell(RUN_SCRIPT_2, LOGFILE)
  

где оболочка

 class Shell():
    """
    Base class for the shell script object which
    is under testing.
    """

    def __init__(self, path_to_script, path_to_log=None):
        """
        executes shell script and store results
        of STDOUT and STDERR into appropriate attributes
        """
        self.path_to_log = path_to_log
        # clear log file before run
        if self.path_to_log:
            open(self.path_to_log, 'w').close()

        shell = subprocess.Popen([path_to_script],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 shell=True)
        # the line below makes sure shell command execution finished
        self.stdout, self.stderr = shell.communicate()
        self.log_data = self.get_log_data()
  

и путь к файлу_to_script равен

 echo 'Start' 
file="${SOURCE_DIR}/NetworkActivity_5851_3_09-04-2016.done"
    extension="${file##*.}"
    if [ $extension = 'done' ]; then
       files=`basename $file`
       files="${files#*_}"
       files="${files#*_}"
       files="${files%_*}"
       q=_"$files"_
       mask="${file/done/log.gz}"
       mask="${mask/${q}/_*_}"
       r=`ls "${mask}" | wc -l`
       echo $r
       if [ $r = $files ]; then
          rez=0
       else rez=1
       fi    
fi
if [[ $rez -eq 1 ]]; then
        echo "Failure"
else echo "Success"
fi
echo 'Finish'
  

Итак, когда я запускаю path_to_script из терминала, r переменная задает количество файлов, когда я запускаю ее с помощью Python, она устанавливает 0.

Комментарии:

1. @Inian это должен быть номер файла, который имеет имя в качестве шаблона

Ответ №1:

Вы можете сделать это, используя bash только методы манипулирования строками.

 $ inputString="NetworkActivity_5851_2326316_09-04-2016.log.gz"
$ substring="${inputString%%.*}"                                      # Removing the part after the first '.'
$ [[ $substring =~ .*_([[:digit:]] )_.* ]] amp;amp; NUM=${BASH_REMATCH[1]}  # Extracting the number you want to replace 
$ finalString="${substring/$NUM/*}.done"                              # Forming the final string with the extension

$ printf "%sn" "$finalString"
NetworkActivity_5851_*_09-04-2016.done
  

Вы можете объединить эту логику в сценарий оболочки и запустить то же самое для нескольких имеющихся у вас файлов. Вышеуказанные команды, однако, могут быть запущены непосредственно на консоли.

Комментарии:

1. Есть еще одна проблема, если _2326316_ будет _8_ , например. ${substring/$NUM/*}.done заменяет первое вхождение 8. Я пытался ${substring/_$NUM_/_*_}.done , но это заменяет первое вхождение _

Ответ №2:

Ну, я основываюсь на вашем первом абзаце. Надеюсь, я понял проблему! Это мое решение с использованием Perl и регулярных выражений с помощью простой командной строки.

 ~$ gunzip NetworkActivity_5851_2326316_09-04-2016.log.gz amp;amp; perl  -e 'while(<>){print $_ if $_ =~ /NetworkActivity_d _.*_d{2}-d{2}-d{4}.done/}' NetworkActivity_5851_2326316_09-04-2016.log
  

Надеюсь, это поможет!