2016-11-04 82 views
0

我想寫一個fgrep語句從文件中刪除具有完整記錄匹配的記錄。我可以在命令行上執行此操作,但不能在ksh腳本中執行此操作。我使用的代碼歸結於這4行代碼:fgrep帶有包含ksh腳本內部空格的字符串

Header='abc def|ghi jkl' #I use the head command to populate this variable 

    workfile=abc.txt 

    command="fgrep -Fxv \'$Header\' $workfile" >$outfile 

    $command 

當我回聲$command到STDIN命令正是我將在命令行上(用單引號)並工作於命令行。當我在ksh腳本(文件)中執行它時,單引號似乎不被識別,因爲錯誤表明它在空間上解析。

我試過後面的ticks,exec,eval,雙引號而不是單引號,並且沒有使用$command變量。問題依然存在。

+3

當人們試圖建立一個變量'$ cmd'然後「運行它」時,通常是因爲他們試圖做一些shell可以通過不同的路徑解決的問題。你真的**需要運行'$ command'嗎?我會重新集中努力獲得一個正常的shell腳本,然後決定是否真的需要這種額外的間接級別。並且不清楚'$ header'中的'|'字符。在grep註冊表中,代表'OR';在殼中,當然,它是一個「管道」。所以這裏有幾個問題還不清楚。更新你的Q(或者改變你的這個問題的策略)。祝你好運。 – shellter

+0

如果答案解決了您的問題,請點擊旁邊的大號複選標記(✓)並選擇性地對其進行投票(增加投票需要至少15個聲望點)才能接受答案。 如果您發現其他答案有幫助,請投票給他們。接受和投票有助於未來的讀者。請參閱[相關幫助中心文章](http://stackoverflow.com/help/someone-answers)。如果您的問題尚未得到充分解答,請提供反饋。如果您覺得自己找到了最佳解決方案,請將其作爲答案和自我接受。 – mklement0

回答

1

Bash FAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!提供全面的指導 - 儘管它是爲猛砸寫的,大部分適用於KSH爲好。 [1]

如果你想堅持的存儲您的命令變量(定義功能是更好的選擇),使用陣列,繞過引用問題:

#!/usr/bin/env ksh 

Header='abc def|ghi jkl' 

workfile=abc.txt 

# Store command and arguments as elements of an array 
command=('fgrep' '-Fxv' "$Header" "$workfile") 

# Invoke the array as a command. 
"${command[@]}" > "$outfile" 

注意:僅一個簡單命令可被存儲在一個陣列中,並且重定向不能成爲其中的一部分。


[1]實施例使用local創建本地變量,ksh不支持該函數。省略local改爲使用shell全局變量,或使用function <name> {...}語法與typeset而不是local來聲明ksh中的局部變量。

2

我能做到這一點在命令行上,而不是KSH腳本

這裏面有一個簡單,便攜,可靠的使用定界符解決方案。

#!/usr/bin/env ksh 

workfile=abc.txt 
outfile=out.txt 

IFS= read -r Header <<'EOF' 
abc def|ghi jul 
EOF 

IFS= read -r command <<'EOF' 
grep -Fxv "$Header" "$workfile" > "$outfile" 
EOF 

eval "$command" 

說明

(註釋不能被添加到上面的腳本,因爲它們會影響在定界符線)

IFS= read -r Header <<'EOF'     # Line separated literal strings 
abc def|ghi jul        # Set into the $Header variable 
EOF           # As if it were a text file 

IFS= read -r command <<'EOF'     # Command to execute 
grep -Fxv "$Header" "$workfile" > "$outfile" # As if it were typed into 
EOF           # the shell command line 

eval "$command"        # Execute the command 

的上面的例子與稱爲的文本文件相同頭。TXT,其中包含的內容:abc def|ghi jul和鍵入以下命令:

  • grep -Fxvf header.txt abc.txt

腳本除了命令行操作不同作爲結果的定界符地址問題引用/擴展/轉義問題。

一個字謹慎關於eval

在這個例子中使用的eval是具體的。請參閱Eval command and security issues以瞭解有關eval如何被濫用以及可能導致非常有害的結果的信息。


更多詳細內容/備用實例:

爲了完整,清楚,並且這一概念適用於其它情況的能力的緣故,有關定界符和替代示範的一些說明:

這在這個例子中,定界符的實施是SP ecifically設計有以下條件:

  • 文字的內容串分配到變量(使用'EOF'
  • 使用eval命令的評估和執行heredoc本身內的引用變量。

文件或定界符?使用定界符的grep -Ffgrep)相結合的

優勢之一,是把腳本的一部分,就好像它是一個普通文件的能力。

案例文件:

  • 你要經常粘貼「模式」行到該文件,並根據需要將其刪除,而不必修改腳本文件

案例定界符:

  • 你在特定的文件已經存在的環境中應用的腳本,你要反對它匹配特定的確切文字圖案。

例子:

  • 場景:我有5臺VPS服務器,我想一個腳本來產生一個新的fstab文件,但,以確保它不包含準確的行:
  • /dev/xvda1 /    ext3 errors=remount-ro,noatime,barrier=0 0  1

這種情況適合這個問題中解決的情況類型。我可以在這個答案中使用的樣板從上面的代碼並修改它如下:

#!/usr/bin/env ksh 

workfile=/etc/fstab 

IFS= read -r Header <<'EOF' 
/dev/xvda1/    ext3 errors=remount-ro,noatime,barrier=0 0  1 
EOF 

IFS= read -r command <<'EOF' 
grep -Fxv "$Header" "$workfile" 
EOF 

eval "$command" 

這將給我一個新的fstab文件,沒有包含在定界符行。

+0

僅供參考 - eval,exec這些不起作用。我找到了解決方案。使用-f或--file選項調用fgrep。我可以將匹配字符串放在指定的文件中。該字符串可以包含空格,單引號,雙引號等。 – Norah

+0

這很好,你需要清楚你想要實現什麼。 - 不清楚你是想特別使用一個命令變量,還是隻想讓fgrep工作。 – hmedia1

+1

Your here-doc解決方案_is_ robust,但我仍然不會推廣它,因爲通常很難理解'eval'的全部含義,並且有更好的非'eval'解決方案可用。相比之下,你的第一個解決方案是不健壯的,我鼓勵你去除它(例如,試着用'Header =「a'b」')。 – mklement0

相關問題