파일의 한 줄을 해당 줄의 일부로 바꾸기

파일의 한 줄을 해당 줄의 일부로 바꾸기

다음 명령을 사용하여 우분투 상자에 설치된 프로그램 목록을 얻었습니다.apt list --installed

이것은 목록의 일부입니다.

wdiff/xenial,now 1.2.2-1build1 amd64 [installed,automatic]
wget/xenial-updates,xenial-security,now 1.17.1-1ubuntu1.5 amd64 [installed]
whiptail/xenial,now 0.52.18-1ubuntu2 amd64 [installed]
xauth/xenial,now 1:1.0.9-1ubuntu2 amd64 [installed]
xdg-user-dirs/xenial-updates,now 0.15-2ubuntu6.16.04.1 amd64 [installed]
xfsprogs/xenial-updates,now 4.3.0+nmu1ubuntu1.1 amd64 [installed]
xkb-data/xenial,now 2.16-1ubuntu1 all [installed]

프로그램 이름과 버전이 필요합니다. 예를 들면
wdiff/xenial,now 1.2.2-1build1 amd64 [installed,automatic] 다음과 같습니다 .
wdiff 1.2.2-1build1

나는 이 명령이 작동하도록 설계했습니다.

apt list --installed  | sed -r 's@/@ @g' | awk '{print $1 "\t" $3}'  | sort -u

입력 파일의 행 일부를 포함하는 새 파일을 생성하기 위해서만 sed를 사용하는 방법을 알고 싶습니다.

이 정규식은 다음과 같습니다. ^([^\/]+)\/[^\s]+\s([^\s]+)

  • 줄의 처음부터 첫 번째/
  • 첫 번째 공백 무시
  • 첫 번째 공간을 두 번째 공간 이후로 캡처

sed를 사용하여 캡처 그룹을 역참조하고 새 출력을 구성할 수 있어야 합니다.

apt list --installed | sed -r 's/^([^\/]+)\/[^\s]+\s([^\s]+)/\1 \2/'

그러나 출력이 내가 기대했던 것과 일치하지 않는 것 같습니다.

wdiff   [installed,automatic]
wget/xenial-updates,xenial-security,now 1.17.1-1ubuntu1.5 amd64 [installed]
whiptail    [installed]
xauth   [installed]
xdg-user-dirs/xenial-updates,now 0.15-2ubuntu6.16.04.1 amd64 [installed]
xfsprogs/xenial-updates,now 4.3.0+nmu1ubuntu1.1 amd64 [installed]
xkb-data    [installed]

무엇이 잘못되었나요?

답변1

무엇이 잘못되었나요? 잘못된 그룹을 포착하고 유지하려는 마지막 일치 항목 이후 입력 문자열의 끝까지 삭제하는 대신 공백이 아닌 다음 항목으로 삭제하고 있습니다.

sed -r 's/^([^\/]+)\/[^\s]+\s([^\s]+)/\1    \2/'

([^/]+)   #capture everything up to /, OK
/         #discard the /. OK
[^\s]     #discard the next non white-space group, this is the bit you actually want
\s        #discard the whitespace
([^\s]+)  #capture the next non-whitespace group
#leave anything after the last non-whitespace found

모든 이스케이프 처리로 인해 가독성이 떨어지기 때문에 아마도 이 작업을 수행하게 될 것입니다. 청소하면 디버깅에 도움이 됩니다

sed -E 's|([^/]*)[^ ]* +([^ ]*).*|\1 \2|' infile | column -t

([^/]*)    #capture up to the /
[^ ]* +    #discard until the space and any spaces
([^ ])     #capture the next character group until a space
.*         #discard to the end of the string

전역 일치( )를 지정하지 않으면 앵커가 s///g필요하지 않습니다 .^

|일치 문자열에서 불필요한 이스케이프를 피하기 위해 구분 기호 로 사용됩니다.

column -t여러 공백보다 더 나은 정렬

답변2

다음 (최적화되지 않은) 정규 표현식을 사용해 보십시오:

$ sed 's/\(^.*\)\(\/[^ ]* \)\([^ ]* \)\([^ ]* \)\([^ ]*\)/\1 \3/' infile
wdiff 1.2.2-1build1 
wget 1.17.1-1ubuntu1.5 
whiptail 0.52.18-1ubuntu2 
xauth 1:1.0.9-1ubuntu2 
xdg-user-dirs 0.15-2ubuntu6.16.04.1 
xfsprogs 4.3.0+nmu1ubuntu1.1 
xkb-data 2.16-1ubuntu1 

관련 정보