[英]Find, Replace or Insert - command Line
我有類似的清單:
What do you want to do?
Import a text file by opening it in Excel
Import a text file by connecting to it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
使用SED,我可以在“ connecting”上找到匹配項並替換行:
sed 's^.*connecting.*^Import a text file by opening it^g' crontab
這應該將上面的列表更改為:
What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
但是,我需要做的是:
如果存在包含單詞connecting
,則替換該行;如果該行不存在,則將其作為新行添加到列表的末尾。
我知道我可以執行echo "Import a text file by opening it" >> list
,這會將行添加到列表的末尾,但是無論如何,我可以在一個命令中執行此操作嗎? 還是可以在一個實例中運行的命令?
謝謝
一種簡單的方法是使用awk
:
awk 'BEGIN { s = "Import a text file by opening it" } /connecting/ { $0 = s; n = 1 } 1; END { if(!n) print s }' filename
如下所示:
BEGIN { # Before anything else:
s = "Import a text file by opening it" # Remember the string by a shorter
# name so we don't have to repeat it
}
/connecting/ { # If a line contains "connecting",
$0 = s # replace the line with that string
n = 1 # and raise a flag that we've done so.
}
1 # print
END { # in the end:
if(!n) { # If the string wasn't yet printed,
print s # do it now.
}
}
另外,您可以使用sed
的保持緩沖區。 例如:
sed '1 { x; s/.*/Import a text file by opening it/; x; }; /connecting/ { s/.*//; x; }; $ { G; s/\n$//; }' filename
其工作原理如下:
1 { # while processing the first line
x # swap hold buffer, pattern space
s/.*/Import a text file by opening it/ # write text to pattern space
x # swap back.
} # Now the hold buffer contains the
# line we want to insert, and the
# pattern space the first line.
/connecting/ { # For all lines: If a line contains
# "connecting"
s/.*// # empty the pattern space
x # swap in hold buffer.
# If this happened, the hold buffer
# will be empty and the pattern space
# will contain "Import a ..."
}
$ { # Last line:
G # Append hold buffer to pattern space.
# If the hold buffer is empty (i.e.,
# was used somewhere else), this
# appends a newline, so
s/\n$// # remove it if that happened.
}
請注意, sed
代碼取決於以下事實:只有一行包含“ connecting”。 如果有更多這樣的行,則將它們替換為空行,因為當第二行出現時,保持緩沖區為空。 可以處理這種情況,但是您必須決定在其中應該發生什么。 既然您在評論中回答說只有這樣一行,所以我不需要猜測。
您可以使用與sed類似的正則表達式語法嘗試perl ,但對這些問題的功能要強大得多。 只要完成至少一個替換,它就簡單地設置一個標志。 解析完整個文件后,如果未設置$flag
變量,請在END {}
塊中添加注釋:
perl -pe '
s/^.*connecting.*$/Import a text file by opening it/ and $done = 1;
END { printf qq|%s\n|, q|Import a text file by opening it| unless $done }
' infile
找到該行后,將產生:
What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
當找不到它時,將產生:
What do you want to do?
Import a text file by opening it in Excel
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
Import a text file by opening it
如果出現多次,請同時更改兩者,但不添加任何內容:
What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Import a text file by opening it
Change the separator in all .csv text files
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.