Извлечь часть строки до определенной строки

Извлечь часть строки до определенной строки

Предположим, у меня есть файл со строками вроде:

/java/jdkxx/jvm_jdk/bin/opt
/java/jre/jre_jvm/bin/opt
/foo/bar/bin/other/stuff/here

Есть ли способ извлечь часть строк до bin. Я имею в виду, предположим, что эти строки находятся в file.txtто время

$ <some_command> file.txt 
/java/jdkxx/jvm_jdk/bin/
/java/jre/jre_jvm/bin/
/foo/bar/bin/

решение1

Есть много способов сделать это. Вот некоторые из них:

# greedily caputure up to the last slash
grep -o '.*/bin/' file.txt
# remove all non-slash chars from the end of each line
sed 's#\(/bin/\).*$#\1#' file.txt
# using slash as a delimiter, blank out the last field
awk -F/ -v OFS=/ '{for (i=1; i<=NF; i++) if ($i == "bin") {NF=i; break}} 1' file.txt

решение2

Чистый bash-способ:

while read -n line
do
    [[ $line =~ /bin/ ]] && printf "%s\n" "${line/%\/bin\/*//bin/}"
done

решение3

Что, нет Perl?

perl -ne 's#/bin\K.*## && print' file

Если вы знаете, чтовселинии содержат нужный вам шаблон, вы можете упростить его до:

perl -pe 's#/bin\K.*##' file

Это \Kвыражение PCRE, которое означает «игнорировать все, что находится перед \K».


Вы также можете делать такие вещи, как

awk -F"/bin" '{print $1FS}' file

Это устанавливает разделитель полей awk ( FS) в /bin, а затем печатает первое поле и значение FS(которое равно /bin). Это, опять же, предполагает, что вам нужна каждая строка. Если нет, используйте это:

awk -F"/bin" '($2){print $1FS}' file

решение4

Наряду с другими хорошими ответами, вы также можете попробовать следующее, которое гарантирует, что все, что находится после /bin/, не будет напечатано:

grep -Po ".*/(?<=/bin/)" file

Пример:

$ cat test_file 
/java/jdkxx/jvm_jdk/bin/opt
/java/jre/jre_jvm/bin/opt/home

$ grep -Po ".*/(?<=/bin/)" test_file 
/java/jdkxx/jvm_jdk/bin/
/java/jre/jre_jvm/bin/

Здесь мы используемПКРЕс позитивным взглядом назад, (?<=/bin/)чтобы убедиться, что мы движемся только до того места /, где мы /bin/наконец оказались.

Связанный контент