我想在文件中添加更多終端/etc/securetty
。更具體地說,我想添加pts/n
, wheren
位於範圍內0-9
(如果不存在)。這可以透過sed
命令實現嗎?我的內容如下/etc/securetty
:
# Local X displays (allows empty passwords with pam_unix's nullok_secure)
pts/0
pts/1
pts/2
pts/3
我嘗試過類似的事情:
sudo sed '+pts/3+a pts/4' /etc/securetty
這給了以下錯誤:
sed: -e expression #1, char 3: extra characters after command
答案1
當我們遇到相應的線時,我們記下分數/數字。該-p
選項將autoprint
行。當我們到達時,eof
我們提取哈希值%h
並將其通過grep
過濾器傳遞,以確定哪些終端沒有列印,然後我們使用map
它來準備格式。
perl -lpe 'm|^pts/([0-9])$| and $h{$1}++;
END{ print for map { "pts/$_" } grep { !$h{$_} } 0 .. 9; }
' /etc/securetty
我們用hold space
數字 0 1 2 ... 9 初始化。pts/[0-9]
在 處eof
,我們取得保留空間,如果找到任何數字,則應將其修改為正確的格式並列印出來。
sed -e '
# initialize the hold space with 0 1 ... 9
1{x;s|.*|'"$(echo {0..9})"'|;x}
# whatever be the line, it needs to be printed
p
# we meet a valid pts/ line
\|^pts/[0-9]$|{
# the hold space gets appended to the pattern space
G
# grab what is the pts number and search for it in the hold and
# delete itand store back the changes into hold space.
s|^pts/\([0-9]\)\n\(.*\)\1 |\2|;h
}
# weve not arrived at the eof and weve processed the input so go no further
$!d
# we are at the eof, so we bring back the hold space. just in case all
# numbers were dealt with up, we simply bail out. Else, prepend the str
# pts/ to the numbers present and simply were home
g;/[0-9]/!d;s/ //g
s|[0-9]|pts/&\n|g;s/.$//
# *TIP*: Sprinkle the l, list pattern space at various places to see
# whats going on.
' /etc/securetty
答案2
若要在遺失時新增單行,可以透過刪除每個出現並將其附加到末尾來完成:
sed -n '/pattern/!p;$a pattern'
但重複 10 個模式就很糟糕了。
sed '/pts\/[0-9]/d;$a pts/0 ...
如果要刪除最後一行將會失敗。所以反過來說,假設第一行是唯一以 開頭的行#
:
sed '/#/a pts/0\
pts/1\
pts/2\
pts/3\
pts/4\
pts/5\
pts/6\
pts/7\
pts/8\
pts\9
/pts\/[0-9]/d'
可惡的。我建議在這種情況下使用不同的工具。
答案3
刪除任何/所有pts/N
行,然後將它們全部加回:
{ grep -xv '^pts/[0-9]$' /etc/securetty; printf 'pts/%d\n' {0..9}; } > /etc/securetty.new
cat /etc/securetty.new
mv /etc/securetty.new /etc/securetty
您也可以使用您最喜歡的文字處理工具一次完成此操作,例如ed
ed -s /etc/securetty <<IN
g/^pts\/[0-9]$/d
.r ! printf pts/\%d\\\n {0..9}
,p
q
IN
(替換,p
為w
就地編輯)或sed
{ printf '%s\\\n' '$a' pts/{0..8}
printf '%s\n' 'pts/9' '/^pts\/[0-9]$/d'
} | sed -f- /etc/securetty
這與普通的幾乎相同
sed '$a\
pts/0\
pts/1\
pts/2\
pts/3\
pts/4\
pts/5\
pts/6\
pts/7\
pts/8\
pts/9
/^pts\/[0-9]$/d' /etc/securetty
(使用sed
和-i
就地編輯文件)
答案4
sed
逐行處理文件,很難讓它「記住」跨行的任何資訊。
您可以使用grep
來查明文件是否包含給定模式;使用-f
,您可以同時提供多個模式。以下產生完整清單pts/0
.. pts/9
,然後刪除給定檔案中已存在的模式,並將剩餘的模式新增至檔案:
#!/bin/bash
printf 'pts/%d\n' {0..9} \
| grep -vFf "$1" - >> "$1".new
mv "$1".new "$1"