web-dev-qa-db-fra.com

Extraire une partie d'une ligne jusqu'à une chaîne particulière

Supposons que j'ai un fichier avec des lignes comme:

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

Est-il possible d'extraire une partie des lignes jusqu'à bin. Je veux dire, supposons que ces lignes sont à file.txt alors

$ <some_command> file.txt 
/Java/jdkxx/jvm_jdk/bin/
/Java/jre/jre_jvm/bin/
/foo/bar/bin/
3
rɑːdʒɑ

Il y a plusieurs façons de le faire. Voilà quelque:

# 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
8
glenn jackman

Une façon pure bash:

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

Quoi, pas de Perl?

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

Si vous savez que toutes les lignes contiennent le motif souhaité, vous pouvez simplifier pour:

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

Le \K est une expression PCRE qui signifie "tout ignorer avant le \K".


Vous pouvez aussi faire des choses comme

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

Cela définit le délimiteur de champ de awk (FS) sur /bin, puis affiche le premier champ et la valeur de FS (qui est /bin). Celui-là, encore une fois, suppose que vous voulez chaque ligne. Sinon, utilisez celui-ci à la place:

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

En python:

python3 -c "for l in open('f').readlines(): print(l[:l.find('/bin')+5])"

/Java/jdkxx/jvm_jdk/bin/
/Java/jre/jre_jvm/bin/

où f est le chemin d'accès au fichier (entre guillemets simples).

3
Jacob Vlijm

En plus d’autres bonnes réponses, vous pouvez également essayer ce qui suit pour vous assurer que tout ce qui se trouve après /bin/ ne sera pas imprimé:

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

Exemple:

$ 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/

Nous utilisons ici le PCRE avec une apparence positive (?<=/bin/) pour nous assurer que nous ne prenons que jusqu'au /, où nous avons enfin /bin/.

2
heemayl