BASH의 기록 명령에서 특정 문자열을 포함하는 모든 항목을 제거하는 방법은 무엇입니까?

BASH의 기록 명령에서 특정 문자열을 포함하는 모든 항목을 제거하는 방법은 무엇입니까?

특정 문자열을 포함하는 bash 쉘 기록에서 모든 항목을 제거하는 명령이나 방법이 있습니까? 이는 비밀번호가 포함된 명령을 기록에서 제거하는 데 유용합니다. 각 기록 항목을 번호별로 제거할 수 있다는 것을 알고 있지만 문제는 한 번에 하나의 항목만 삭제하고 새 항목을 제거하려면 매번 번호를 제거해야 한다는 것입니다.

예. History 명령에 비밀번호 abcabc가 포함된 5개의 항목이 표시되고 문자열 abcabc가 포함된 기록 명령에서 모든 항목을 제거하고 싶습니다.

975  2019-03-15 11:20:30 ll
  976  2019-03-15 11:20:33 ll cd
  977  2019-03-15 11:20:36 ll CD
  978  2019-03-15 11:20:45 chown test1:test1 CD
  979  2019-03-15 11:20:53 chown test1:test1 ./CD
  980  2019-03-15 11:20:57 chown test1:test1 .\CD
  981  2019-03-15 11:22:04 cd /tmp/logs/
  982  2019-06-07 10:36:33 su test1
  983  2019-08-22 08:35:10 su user1
  984  2019-08-22 08:35:15 /opt/abc/legacy.exe -password abcabc
  985  2019-09-24 07:20:45 cd /opt/test1/v6r2017x
  986  2019-09-24 07:20:46 ll
  987  2019-09-24 07:21:18 cd /tmp/
  988  2019-09-24 07:21:19 ll
  989  2019-09-24 07:21:24 cd linux_a64/
  990  2019-09-24 07:21:25 /opt/abc/legacy.exe -password abcabc
  991  2019-09-24 07:24:03 cd  build/
  992  2019-09-24 07:24:04 ll
  993  2019-09-24 07:24:07 cd ..
  994  2019-09-24 07:24:10 /opt/abc/legacy.exe -password abcabc
  995  2019-09-24 07:24:15 cd someapp/bin
  996  2019-09-24 07:24:21 ll
  997  2019-09-24 07:24:33 cd .
  998  2019-09-24 07:24:35 cd ..
  999  2019-09-24 07:24:36 ll

아래와 같이 오류가 발생한 다음 명령을 시도했습니다.

servername:~ # sed -i 'g/abcabc/d' /home/user1/.bash_history
sed: -e expression #1, char 2: extra characters after command

예상 사항: 오류가 없으며 abcabc 문자열이 포함된 모든 항목이 제거되어야 합니다.

답변1

@cprn의 답변과 유사하지만 awk(대신 cut) 및 함수를 사용하는 또 다른 하나는 다음과 같습니다.

function del_word_history () {
  if [ -z "${1}" ]; then return false; fi
  mapfile -t result <<< "$(history | grep "${1}" | tac | awk '{print $1}')"
  for idx in "${result[@]}"; do
    history -d $idx
  done
}
  • tac출력 라인을 반전시킵니다(일부 게시물에서는 모든 시스템에 공통적이지 않다고 지적했습니다).
  • [-z $1 ]: true함수에 전달된 첫 번째 인수( $1)가 비어 있는 경우.
  • mapfile -t(매뉴얼 페이지;일부 가이드): stdin배열 변수를 읽습니다( result).
    • "${result[@]}"배열을 반환합니다
  • awk '{print $1}'(GNU 사용자 가이드,간략한 가이드,매뉴얼 페이지): 일치 항목을 식별하고 처리하는 데 모두 사용됩니다. 공백(기본값)으로 구분된 데이터를 분할하여 $n변수에 저장합니다.
  • '{pring $1}'다음을 위해 읽습니다print첫 번째 단어에 대해 작업 수행.

용법:

del_word_history history
del_word_history abcabc
history -w

아래는더 깨끗한 솔루션여러 줄 항목의 다른 단어가 아닌 의 idx숫자를 얻었는지 확인합니다 .history

function del_word_history () {
  if [ -z "${1}" ]; then return false; fi
  mapfile -t lines <<< "$(history | grep "${1}" | tac)"
  for line in "${lines[@]}"; do
    idx="$(printf '%s' "${line}" | awk '{ if ($1 ~ /^[0-9]+$/) { print $1 } }')"
    if [ -n "${idx}" ]; then
      echo "removing line ${idx}"
      history -d $idx
    fi
  done
}

주요 차이점은 다음과 같습니다.

  • lines우리는 다음을 통해 배열 변수의 전체 라인을 얻습니다.mapfile
  • awk '{ if ($1 ~ /^[0-9]+$/) { print $1 }}'각 줄의 첫 번째 단어가 숫자인지 확인하고 stdout동일한 첫 번째 단어인지 확인합니다(그리고 idx변수에 도달함).
  • [ -n ${idx}" ] just checks ifidx`가 비어 있지 않습니다

답변2

나는 그것이 오래되었다는 것을 알고 있지만 방금 다음과 같이 루프에서 수행했습니다.

for ln in $( history | grep my_phrase | cut -f2 -d' '); do
    history -d $ln
done
  • $(...)- 명령 대체, stdout반환...
  • cut -f2 -d' '- 공백으로 구분된 출력의 두 번째 열, 즉 줄 번호를 잘라냅니다.
  • history -d $ln- 기록에서 주어진 줄 번호를 제거합니다.

쉽게 복사하여 붙여넣을 수 있는 하나의 라이너:

for ln in $( history | grep my_phrase | cut -f2 -d' '); do history -d $ln; done

답변3

를 사용하여 sed에서 항목을 제거 할 수 있습니다 .bash_history.
그러나 CLI에서 비밀번호를 다시 입력하지 않도록 하기 위한 비밀번호이므로 .bashrc파일을 편집하고 가 있는 행이 또는 HISTCONTROL으로 설정되어 있는지 확인하는 것이 좋습니다 . 이렇게 하면 명령을 입력할 수 있고 공백으로 시작하는 경우 기록에 넣지 않을 수 있습니다. ignorebothignorespacebash

promtpt:$ sed -i '/abcabc/d' /home/user/.bash_history

$와 명령 사이의 공백으로 인해 bash 기록에서 해당 행이 무시됩니다.

-i: 파일을 인라인으로 편집한다는 의미입니다.
d결국 사이에 표현식이 포함된 줄을 제거하는 것을 의미합니다 /.

이 솔루션은 Linux에서만 작동합니다 GNU sed.

관련 정보