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

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

다음을 사용하여 우분투 상자에 설치된 프로그램 목록을 얻었습니다.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 

관련 정보