2017-08-26 37 views
0

我想解析一個命令行參數列表(包含在特殊的"[email protected]" Bash變量中),該列表將被傳遞給Linux ls二進制文件。從Bash中的參數列表中提取參數列表的位置路徑參數

的參數可以任選地包含關鍵字參數像-h--color--hide 'pattern',並且它們可以任選地包含一個目錄或文件路徑(絕對/home,相對./bin或隱式地相對Documents)在任何位置。

有沒有辦法從列表中只提取位置路徑參數,如果有任何被包含?

如果無法合理排除所有邊緣情況,我們至少可以實現目標,並在路線參數作爲最後一個參數提取時抽取路徑參數?

在情況下,它可以幫助爲背景下,我要與awk進一步處理路徑參數在下一步驟由(以"show git branch in ls -l" on Ask Ubuntu相)附加進一步的信息以每行修改的ls -alF輸出。在這裏,我有問題,如果我運行例如ls -alF /home,我在輸出中輸入了關於./../的條目,然後awk將作爲到當前工作目錄的相對路徑處理,而不是處理到指定的/home


實際腳本(Bash函數)可以在Ask Ubuntu上面的鏈接答案中找到。下面是跳過調用外部git命令,並分析其輸出的最小版本:

lg(){ 
    ls -alF "[email protected]" | 
    awk '{ 
     # Split into columns 1-8 and 9+ (file name): 
     match($0, /^(\S+\s+){8}(.+)$/, f); 
     # do something with the file name using an external command 
     # result is stored in b, e.g. "(master)" or an empty string 
     b=f[2]; 
     print $0, b 
    }' 
; } 

示例輸出(包括外部調用原有功能):

$ lg 
total 48 
drwxrwxr-x 12 bytecommander bytecommander 4096 Aug 26 14:48 ./ 
drwxr-xr-x 74 bytecommander bytecommander 4096 Aug 26 15:30 ../ 
drwxrwxr-x 6 bytecommander bytecommander 4096 Aug 26 14:43 git1/ (master) 
drwxrwxr-x 7 bytecommander bytecommander 4096 Aug 26 14:42 git2/ (develop) 
drwxrwxr-x 4 bytecommander bytecommander 4096 Aug 26 14:45 no-git/ 
-rw-rw-r-- 1 bytecommander bytecommander 0 Aug 26 14:42 regular-file 

現在,如果我的當前工作目錄是例如git1(這是一個存儲庫),我運行它,如lg /homels輸出中的./條目將正確對應於/home,但我添加的存儲庫信息錯誤地是當前工作目錄中的一個,即git1。父目錄條目相同../

+0

什麼是你真正想幹什麼?處理'ls'的輸出是一個好主意。 – chepner

+0

@chepner我認爲我最後的目標在最後一段中有很好的描述。我想要實現的是將ls -alF的輸出保持原樣並通過將一些git元信息附加到輸出中列出的所有目錄來擴展它。我有一個工作解決方案(見鏈接),目前存在的問題是'.' /'..'條目相對於工作目錄而不是可選的指定位置參數。是的,我知道解析'ls'並不是最好的選擇,但另一種方法是重寫'ls',我想這樣做更少。 –

+0

你也許試圖寫一個這就是所謂的像腳本'的MyScript -alF/home'和內部調用'LS「$ @」'你要那麼也是腳本中調用'的awk「...」/home'?如果這樣awk調用就會是'awk'...'「$ {」#}「'在bash中 - 這就是你想要的嗎?如果不是,則用一個具體的示例腳本和樣本輸入預期輸出來澄清你的問題,即a [mcve]。 –

回答

1

如果您對Perl有問題,那麼我建議使用Getopt :: Long包來解析參數。這裏有一個例子:

#!/usr/bin/perl 
use Getopt::Long; 

my @args = @ARGV; 

GetOptions(
    'a'   => \$opt{'a'}, 
    'all'   => \$opt{'all'}, 
    'A'   => \$opt{'A'}, 
    'almost-all' => \$opt{'almost-all'}, 
    'author'  => \$opt{'author'}, 
    'b'   => \$opt{'b'}, 
    'escape'  => \$opt{'escape'}, 
    'block-size=s' => \$opt{'block-size'}, 
    # ... 
    'version'  => \$opt{'version'} 
) 
or die "Invalid options: @args\n"; 

my @fileargs = @ARGV; 
print "ls args: @args\n"; 
print "file args: @fileargs\n"; 

例如perl script.pl -a --author file1 file2將打印ls args: -a --author file1 file2file args: file1 file2。您可以添加更多代碼來處理文件參數。

至於相對路徑名問題:我建議運行find -maxdepth 1 fileordir而不是ls fileordir來獲取絕對路徑。

+0

我是否可以只獲取位置路徑參數並簡單忽略其他任何內容,而無需首先在某處配置所有可能的參數? –

+0

那麼你可以把所有東西都扔掉,因爲ls只知道' - (\ w | - \ w +(= \ w +)?')形式的參數'',但這不是一點點破解? – yacc

1

我最好的猜測,到目前爲止是你寫的,你要調用的腳本「的MyScript」:

myscript -<ls-args> <path> 

和裏面的MyScript做:

ls "[email protected]" 
awk 'stuff' "${!#}" 

如果這不是你'尋找然後編輯你的問題來澄清。

+0

「'$ {!#}」'在這裏做什麼? –

+0

'$#'是傳遞給'myscript'的參數的個數,所以'$ {!#}'是傳遞給'myscript'的最後一個參數的值。 –