我似乎沒有在bash中很簡單的東西失敗。我有一個字符串變量,保存目錄的完整路徑。我想將其中的最後一個兩個目錄分配給另一個字符串。舉例來說,如果我有:bash:提取路徑名的最後兩個dirs
DIRNAME = /a/b/c/d/e
我想:
DIRNAME2 = d/e
我敢肯定有一個簡單的bash結構或sed
命令,將做到這一點,但它逃避我。我有點像basename
或dirname
的廣義版本,不只是返回名稱的極端部分。
謝謝! 戴夫
我似乎沒有在bash中很簡單的東西失敗。我有一個字符串變量,保存目錄的完整路徑。我想將其中的最後一個兩個目錄分配給另一個字符串。舉例來說,如果我有:bash:提取路徑名的最後兩個dirs
DIRNAME = /a/b/c/d/e
我想:
DIRNAME2 = d/e
我敢肯定有一個簡單的bash結構或sed
命令,將做到這一點,但它逃避我。我有點像basename
或dirname
的廣義版本,不只是返回名稱的極端部分。
謝謝! 戴夫
DIRNAME=/a/b/c/d/e
D2=$(dirname $DIRNAME)
DIRNAME2=$(basename $D2)/$(basename $DIRNAME)
,或者在一個行:
DIRNAME2=$(basename $(dirname $DIRNAME))/$(basename $DIRNAME)
,除非你是大舉進入受虐狂不要嘗試遊戲的反引號。如果路徑中可能有空格,請在變量名稱周圍使用雙引號。
這將適用於幾乎所有的shell(即使是第七版Unix Bourne shell - 如果你終究沉迷於使用反引號的受虐狂)。在bash
中,還有其他可用的機制 - 其他答案說明了許多選項中的一些,但expr
也是一個老派解決方案(它也出現在第7版Unix中)。
DIRNAME2=`basename \`dirname "$DIRNAME"\``/`basename "$DIRNAME"`
(兩個嵌套層次是不是太可怕了;三是得到棘手!)
哇,這是我在stackoverflow上的第一篇文章,我對這些回覆非常滿意!我去了/你的一行basename-dirname答案,因爲這只是一個腳本,我將作爲提交數字作業的一部分運行。但是我會保存這個線程以獲得許多華麗的bash字符串技巧! – user1059256
+1,這是最多的語義解決方案。 – harpo
我覺得有使用水珠較短的方式,但:
$ DIRNAME='a/b/c/d/e'
$ LAST_TWO=$(expr "$DIRNAME" : '.*/\([^/]*/[^/]*\)$')
$ echo $LAST_TWO
d/e
我不知道的方法專門爲微調路徑,但你肯定能做到這一點與bash's regular expression matching:
DIRNAME=/a/b/c/d/e
if [[ "$DIRNAME" =~ ([^/]+/+[^/]+)/*$ ]]; then
echo "Last two: ${BASH_REMATCH[1]}"
else
echo "No match"
fi
注意:爲了處理路徑中的一些允許但不常見的東西,我在這裏將模式設置得比您想象的複雜一點:它修剪尾部斜槓並容忍多個(冗餘)斜槓最後兩名之間ES。例如,在「/ a/b/c // d //」上運行它將匹配「c // d」。
function getDir() {
echo $1 | awk -F/ '
{
n=NF-'$2'+1;
if(n<1)exit;
for (i=n;i<=NF;i++) {
printf("/%s",$i);
}
}'
}
dir="https://stackoverflow.com/a/b/c/d/e"
dir2=`getDir $dir 1`
echo $dir2
您可以從上次從這個函數得到任何數量的目錄。 對於您的情況下運行它,
dir2=`getDir $dir 2`;
輸出:/ d/E
DIRNAME="a/b/c/d/e"
DIRNAME2=`echo $DIRNAME | awk -F/ '{print $(NF-1)"_"$(NF)}'`
DIRNAME2 then has the value d_e
切換到任何你想下劃線。
我更喜歡盡我所能地使用builtins,以避免創建不必要的進程。因爲你的腳本可能在Cygwin或其他操作系統下運行,而這些操作系統的創建過程非常昂貴。
我覺得它不是那麼漫長,如果你只是想提取2個迪爾斯:
base1="${DIRNAME##*/}"
dir1="${DIRNAME%/*}"
DIRNAME2="${dir1##*/}/$base1"
這也可避免參與執行其他命令的特殊字符的問題。
+1最佳解決方案恕我直言。 – helpermethod
dirname=/a/b/c/d/e
IFS=/ read -a dirs <<< "$dirname"
printf "%s/%s\n" "${dirs[-2]}" "${dirs[-1]}"
我只是把基本名稱和基本名稱目錄名稱的並結合了。 –