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.

관련 정보