파일에 줄이 없으면 어떻게 파일에 여러 줄을 추가할 수 있나요?
예를 들어 여러 전역 별칭을 추가하려면 /etc/bash.bashrc
다음을 사용합니다 .여기 문서:
cat <<-"BASHRC" >> /etc/bash.bashrc
alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
alias brc="nano /etc/bash.bashrc"
BASHRC
이 작업에는 행이 이미 존재하는지 확인하는 방법이 포함되어 있지 않으며 실수로 이 문서를 다시 실행하면 중복 및 충돌이 발생할 수 있다는 비판을 받았습니다.
답변1
파일의 행을 newdata
에 추가하는 간단한 쉘 스크립트입니다 datafile
. newdata
이 문서를 변경하는 것은 간단해야 합니다. 이는 grep
모든 (새로운) 입력 라인이 필요하기 때문에 실제로 매우 효율적이지 않습니다.
target=datafile
while IFS= read -r line ; do
if ! grep -Fqxe "$line" "$target" ; then
printf "%s\n" "$line" >> "$target"
fi
done < newdata
각 줄에 대해 이를 사용하여 고정 문자열 일치(정규식 없음), 전체 줄 일치 및 일치하는 줄의 출력을 억제하기 위해 grep
대상 파일에 이미 존재하는지 확인합니다 . 일치하는 라인이 없으면 거짓 오류 코드가 반환되므로, 부정적인 결과가 참이면 대상 파일에 추가하십시오.-F
-x
-q
grep
에서는 보다 효율적으로 임의의 행을 배열의 키로 처리할 수 있어야 합니다 awk
.awk
$ awk 'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}' datafile newdata
첫 번째 부분은 FNR == NR { lines[$0] = 1; next }
첫 번째 입력 파일의 모든 행을 (연관) 배열의 키로 로드합니다 lines
. 두 번째 부분은 ! ($0 in lines) {print}
다음 입력 라인에서 작동하며 해당 라인이 배열에 없으면 "새" 라인을 인쇄합니다.
생성된 출력에는 새 줄만 포함되므로 원본 파일에 추가해야 합니다. 예 sponge
:
$ awk 'FNR == NR { lines[$0] = 1; next } ! ($0 in lines) {print}' datafile newdata | sponge -a datafile
또는 awk
다음 줄을 마지막 줄에 추가할 수 있습니다. 이렇게 하려면 파일 이름을 다음으로 전달하면 됩니다 awk
.
$ target=datafile
$ awk -vtarget="$target" 'FNR == NR { lines[$0] = 1; next }
! ($0 in lines) {print >> target}' "$target" newdata
here-doc를 사용하려면 리디렉션을 설정하는 것 외에도 awk
(stdin)을 명시적 소스 파일로 추가해야 합니다.-
awk ... "$target" - <<EOF
답변2
이 솔루션은 여러분이 생각하는 것과 약간 다를 수 있지만 별칭이 실제로 정의되어 있는지 확인하고 그렇지 않은 경우 bashrc에 추가하면 됩니다. 비교적 최신 버전의 Bash를 사용한다고 가정하면 ...
# instead of 'alias x=y' form put them in an associative array
declare -A aliases
aliases['a']='apple'
aliases['ba']='banana'
for key in "${!aliases[@]}"; do
if ! alias "$key" > /dev/null 2>&1; then
printf "alias %s='%s'\n" "$key" "${aliases[$key]}" >> /etc/bash.bashrc
fi
done
unset aliases key
. ./scriptname
일반 스크립트로 실행하는 대신 가져옵니다 .
노트:후보 별칭이 많이 있고 이를 연관 배열 형식으로 수동으로 변환하는 것이 조심스러운 경우 다음을 vim
사용하여 파일을 편집하고 이 명령을 실행할 수 있습니다 :%s/\valias *([^=]+)\=['"]?([^'"]+)['"]?$/aliases['\1']='\2'/
.
또는후보 별칭(다른 것은 제외)을 파일(예: /tmp/aliases.txt
) 에 넣고 aliases[..]='..'
스크립트의 줄을 다음으로 바꿉니다.
while IFS= read -r a; do
eval "$a";
done < <(sed -E "s/alias *([^=]+)=['\"]?([^'\"]+)['\"]?$/aliases['\1']='\2'/" /tmp/aliases.txt)
물론 AA를 사용하는 것 외에 다른 방법도 있지만 깨끗하고 사용하기 쉽습니다. 이제 AA를 사용하고 싶습니다. :)
답변3
정확한 일치를 위한 일반적인 솔루션(성능에 최적화되지 않음) 이 파일에는 input
확인할 줄이 포함되어 있습니다.
awk 'FNR==NR { lines[NR]=$0; next; };
{ for(i=1;i<=length(lines);i++) if ($0==lines[i]) matches[i]=1; print; };
END { for(i=1;i<=length(lines);i++)
if (matches[i]==0) print lines[i]; }' input file
시험:
:> cat input
alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
alias brc="nano /etc/bash.bashrc"
:> cat file
a
b
c
alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
d
명령의 출력은 다음과 같습니다 awk
.
a
b
c
alias rss="/etc/init.d/php*-fpm restart && systemctl restart nginx.service"
d
alias brc="nano /etc/bash.bashrc"
답변4
어 허. 이건 어때...
추가하려는 별칭을 파일에 넣으십시오.새로운. 그 다음에...
cp bashrc bashrc.tmp && comm -23 <(sort -u new) <(sort -u bashrc.tmp) >> bashrc && rm -f bashrc.tmp
새로운 별칭에 대해 이 작업을 수행하고bashrc콘텐츠(추가할 때 경쟁 조건을 피하기 위해 임시 파일에 넣기)bashrc) 그리고 실행하세요 comm
. comm
정렬된 파일을 한 줄씩 비교하고 고유하고 일반적인 줄을 표시합니다. 열 2와 3( -23
)을 표시하지 않으므로 결과는 해당 고유 행만 표시됩니다.새로운우리는 그것들을 다음에 추가합니다bashrc. 그게 다야.
(이것은 더 많은 "하나의 라이너"에 대한 탐구에 초점을 맞춘 다른 답변과는 완전히 다른 접근 방식입니다.)