Получить один элемент строки пути, используя bash

6

У меня есть файл ASCII, содержащий пути к файлу, которые я прочитал:

while read p; do echo $p; done < filelist.txt

Файл содержит пути к файлам со следующим шаблоном:

./first/example1/path
./second/example1/path
./third/example2/path

Как я могу получить определенную часть строки пути (от / до / ), например. Мне нужно получить вывод, который печатает:

first
second
third

, а также

example1
example1
example2

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

    
задан mcExchange 24.03.2016 в 11:28
источник

5 ответов

11

Используйте cut :

$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

$ cut -d/ -f2 filelist.txt 
first
second
third

$ cut -d/ -f3 filelist.txt 
example1
example1
example2

-d/ устанавливает разделитель столбцов в / , а -f2 выбирает второй столбец.

Вы можете, конечно, также использовать переменные Bash вместо имени файла или данных канала в команде cut :

cut -d/ -f3 $MyVariable
echo ./another/example/path | cut -d/ -f3
    
ответ дан Byte Commander 24.03.2016 в 11:35
источник
10

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

$ while IFS=/ read -r p1 p2 p3 r; do echo "$p2"; done < filelist.txt 
first
second
third
    
ответ дан steeldriver 24.03.2016 в 13:11
5

Вы можете использовать awk

[email protected]:~$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

[email protected]:~$ awk -F "/" '{print }' filelist.txt
first
second
third

[email protected]:~$ awk -F "/" '{print }' filelist.txt
example1
example1
example2
    
ответ дан Pilot6 24.03.2016 в 11:33
2

Если нам нужен любой элемент пути, лучше всего использовать что-то, что может разбивать строку на поля, например awk , cut , python или perl . Тем не менее, bash также может выполнять задание с заменой параметров, используя замену шаблонов и бросая все в массив.

$> echo ${FILE//\//\ }                                                         
sys class backlight intel_backlight brightness
$> ARRAY=( ${FILE//\//" " } )                                                  
$> echo ${ARRAY[2]}
backlight

$> FILE="./dir1/dir2/file.txt"                                                 
$> ARRAY=( ${FILE//\/" "} )
$> echo ${ARRAY[@]}                                                            
. dir1 dir2 file.txt
$> echo ${ARRAY[1]}
dir1

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

ответ дан Sergiy Kolodyazhnyy 24.03.2016 в 14:12
1

Bash и cut - путь, однако альтернатива с использованием Perl:

perl -F/ -lane 'print(@F[1])' filelist.txt

для второго / -пределенного поля и

perl -F/ -lane 'print(@F[2])' filelist.txt

для третьего / -пределенного поля.

  • -l : включает автоматическую обработку окончания строки. Он имеет два отдельных эффекта. Во-первых, он автоматически сжимает $ / (разделитель входных данных) при использовании с -n или -p. Во-вторых, он присваивает $ \ (разделителю выходной записи) значение octnum, так что в любых операторах печати будет добавлен этот разделитель. Если octnum опущен, то устанавливает $ \ текущее значение $ /.
  • -a : включает режим автоматической установки при использовании с -n или -p. Неявная команда split для массива @F выполняется как первая вещь внутри неявного цикла while, созданного -n или -p.
  • -n : приводит к тому, что Perl принимает следующий цикл вокруг вашей программы, что заставляет его перебирать аргументы в имени файла несколько как sed -n или awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e : может использоваться для ввода одной строки программы;

  • print(@F[N]) : печатает N-е поле.
% cat filelist.txt 
./first/example1/path
./second/example1/path
./third/example2/path
% perl -F/ -lane 'print(@F[1])' filelist.txt
first
second
third
% perl -F/ -lane 'print(@F[2])' filelist.txt
example1
example1
example2
    
ответ дан kos 24.03.2016 в 11:54