Получить один элемент строки пути с помощью bash

У меня есть файл 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, но я не знаком с этим.

1
задан 24 March 2016 в 19:58

4 ответа

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

$ while IFS=/ read -r p1 p2 p3 r; do echo "$p2"; done < filelist.txt 
first
second
third
10
ответ дан 23 May 2018 в 12:37

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

pilot6@Pilot6:~$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

pilot6@Pilot6:~$ awk -F "/" '{print $2}' filelist.txt
first
second
third

pilot6@Pilot6:~$ awk -F "/" '{print $3}' filelist.txt
example1
example1
example2
5
ответ дан 23 May 2018 в 12:37

Если нам нужен какой-либо элемент пути, лучше использовать что-то, что может разбивать строку на поля, такие как 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.

2
ответ дан 23 May 2018 в 12:37

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
1
ответ дан 23 May 2018 в 12:37

Другие вопросы по тегам:

Похожие вопросы: