중요합니다
System.CommandLine
는 현재 미리 보기로 제공되며, 이 설명서는 버전 2.0 베타 5용입니다.
일부 정보는 릴리스되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
이 자습서에서는 System.CommandLine
라이브러리사용하는 .NET 명령줄 앱을 만드는 방법을 보여줍니다. 먼저 하나의 옵션이 있는 간단한 루트 명령을 만듭니다. 그런 다음, 해당 기반으로 빌드하여 여러 하위 명령과 각 명령에 대한 다양한 옵션을 포함하는 더 복잡한 앱을 만듭니다.
이 자습서에서는 다음 방법을 알아봅니다.
- 명령, 옵션 및 인수를 만듭니다.
- 옵션의 기본값을 지정합니다.
- 명령에 옵션 및 인수를 할당합니다.
- 명령의 모든 하위 명령에 옵션을 재귀적으로 할당합니다.
- 여러 수준의 중첩된 하위 명령을 사용합니다.
- 명령 및 옵션에 대한 별칭을 만듭니다.
-
string
,string[]
,int
,bool
,FileInfo
및 열거형 옵션 형식과 작업합니다. - 명령 작업 코드에서 옵션 값을 읽습니다.
- 옵션 구문 분석 및 유효성 검사에 사용자 지정 코드를 사용합니다.
필수 조건
- 최신 .NET SDK
- Visual Studio Code 편집기
- C# 개발 키트
또는
- Visual Studio 2022에서 .NET 데스크톱 개발 워크로드가 설치됨.
앱 만들기
"scl"이라는 .NET 9 콘솔 앱 프로젝트를 만듭니다.
프로젝트에 대한 scl 폴더를 만든 다음 새 폴더에서 명령 프롬프트를 엽니다.
다음 명령을 실행합니다.
dotnet new console --framework net9.0
System.CommandLine 패키지 설치
다음 명령을 실행합니다.
dotnet add package System.CommandLine --prerelease
또는 .NET 10 이상에서 다음을 수행합니다.
dotnet package add System.CommandLine --prerelease
라이브러리가 베타 버전이므로
--prerelease
옵션이 필요합니다.
인수를 파싱합니다
Program.cs의 내용을 다음 코드로 바꿉니다.
using System.CommandLine; using System.CommandLine.Parsing; namespace scl; class Program { static int Main(string[] args) { Option<FileInfo> fileOption = new("--file") { Description = "The file to read and display on the console." }; RootCommand rootCommand = new("Sample app for System.CommandLine"); rootCommand.Options.Add(fileOption); ParseResult parseResult = rootCommand.Parse(args); if (parseResult.GetValue(fileOption) is FileInfo parsedFile) { ReadFile(parsedFile); return 0; } foreach (ParseError parseError in parseResult.Errors) { Console.Error.WriteLine(parseError.Message); } return 1; } static void ReadFile(FileInfo file) { foreach (string line in File.ReadLines(file.FullName)) { Console.WriteLine(line); } } }
앞의 코드는 다음과 같습니다.
Option<FileInfo> fileOption = new("--file")
{
Description = "The file to read and display on the console."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
rootCommand.Options.Add(fileOption);
-
args
을 구문 분석하고--file
옵션에 값이 제공되었는지 확인합니다. 이 경우, 구문 분석된 값을 사용하여ReadFile
메서드를 호출하고0
종료 코드를 반환합니다.
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
ReadFile(parsedFile);
return 0;
}
-
--file
값이 제공되지 않은 경우 사용 가능한 구문 분석 오류를 출력하고1
종료 코드를 반환합니다.
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
- 메서드는
ReadFile
지정된 파일을 읽고 콘솔에 해당 내용을 표시합니다.
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
앱 테스트
명령줄 앱을 개발하는 동안 다음 방법 중 원하는 방법으로 테스트할 수 있습니다.
명령을 실행한
dotnet build
다음 scl/bin/Debug/net9.0 폴더에서 명령 프롬프트를 열어 실행 파일을 실행합니다.dotnet build cd bin/Debug/net9.0 scl --file scl.runtimeconfig.json
다음 예제와 같이
dotnet run
사용하여run
후--
명령 대신 앱에 옵션 값을 전달합니다.dotnet run -- --file bin/Debug/net9.0/scl.runtimeconfig.json
이 자습서에서는 이러한 옵션 중 첫 번째 옵션을 사용 중이라고 가정합니다.
앱을 실행하면 --file
옵션으로 지정된 파일의 내용이 표시됩니다.
{
"runtimeOptions": {
"tfm": "net9.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
}
}
}
그렇다면 --help
을 제공하여 도움말을 표시하도록 요청하면 어떻게 될까요?
--file
가 제공되지 않고 구문 분석 오류가 없는 시나리오를 앱이 아직 처리하지 않기 때문에 콘솔에 아무것도 출력되지 않습니다.
인수 구문 분석 및 ParseResult 호출
System.CommandLine 를 사용하면 지정된 기호(명령, 지시문 또는 옵션)가 성공적으로 구문 분석될 때 호출되는 작업을 지정할 수 있습니다. 작업은 매개 변수를 System.CommandLine.ParseResult
사용하고 종료 코드를 반환하는 int
대리자입니다(비동기 작업도 사용할 수 있음). 종료 코드는 메서드에서 System.CommandLine.Parsing.ParseResult.Invoke
반환되며 명령이 성공적으로 실행되었는지 여부를 나타내는 데 사용할 수 있습니다.
Program.cs의 내용을 다음 코드로 바꿉니다.
using System.CommandLine; namespace scl; class Program { static int Main(string[] args) { Option<FileInfo> fileOption = new("--file") { Description = "The file to read and display on the console." }; RootCommand rootCommand = new("Sample app for System.CommandLine"); rootCommand.Options.Add(fileOption); rootCommand.SetAction(parseResult => { FileInfo parsedFile = parseResult.GetValue(fileOption); ReadFile(parsedFile); return 0; }); ParseResult parseResult = rootCommand.Parse(args); return parseResult.Invoke(); } static void ReadFile(FileInfo file) { foreach (string line in File.ReadLines(file.FullName)) { Console.WriteLine(line); } } }
앞의 코드는 다음과 같습니다.
루트 명령이
ReadFile
호출될 때 호출되는 메서드를 지정합니다.rootCommand.SetAction(parseResult => { FileInfo parsedFile = parseResult.GetValue(fileOption); ReadFile(parsedFile); return 0; });
args
결과를 구문 분석하고 호출합니다.ParseResult parseResult = rootCommand.Parse(args); return parseResult.Invoke();
앱을 실행하면 --file
옵션으로 지정된 파일의 내용이 표시됩니다.
--help
을 제공하여 도움말을 표시하라고 요청하면 어떻게 되나요?
scl --help
다음 출력이 출력됩니다.
Description:
Sample app for System.CommandLine
Usage:
scl [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
--file The file to read and display on the conso
System.CommandLine.RootCommand
기본적으로 도움말 옵션, 버전 옵션 및 Suggest 지시문을 제공합니다.
ParseResult.Invoke
메서드는 구문 분석된 기호의 동작을 호출합니다. 우리 명령에 대해 명시적으로 정의된 작업 또는 System.CommandLine
가 System.CommandLine.Help.HelpOption
에 대해 정의한 도움말 작업일 수 있습니다. 감지된 구문 분석 오류는 표준 오류로 출력되고, 표준 출력에 도움말을 출력하며, 1
종료 코드를 반환합니다.
scl --invalid bla
Unrecognized command or argument '--invalid'.
Unrecognized command or argument 'bla'.
하위 명령 및 옵션 추가
이 섹션에서는 다음을 수행합니다.
- 추가 옵션을 만듭니다.
- 하위 명령을 만듭니다.
- 새 하위 명령에 새 옵션을 할당합니다.
새 옵션을 사용하면 전경 및 배경 텍스트 색과 읽기 속도를 구성할 수 있습니다. 이러한 기능은 Teleprompter 콘솔 앱 자습서인용문 모음을 읽기 위해 사용됩니다.
이 샘플의 GitHub 리포지토리에서 프로젝트 디렉터리로 sampleQuotes.txt 파일을 복사합니다. 파일을 다운로드하는 방법에 대한 자세한 내용은 샘플 및 자습서지침을 참조하세요.
프로젝트 파일을 열고 닫는
<ItemGroup>
태그 바로 앞에</Project>
요소를 추가합니다.<ItemGroup> <Content Include="sampleQuotes.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup>
이 태그를 추가하면 앱을 빌드할 때 텍스트 파일이 bin/debug/net9.0 폴더에 복사됩니다. 따라서 해당 폴더에서 실행 파일을 실행할 때 폴더 경로를 지정하지 않고 이름으로 파일에 액세스할 수 있습니다.
Program.cs
--file
옵션을 만드는 코드 후 읽기 속도 및 텍스트 색을 제어하는 옵션을 만듭니다.Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds per character in a line.", DefaultValueFactory = parseResult => 42 }; Option<ConsoleColor> fgcolorOption = new("--fgcolor") { Description = "Foreground color of text displayed on the console.", DefaultValueFactory = parseResult => ConsoleColor.White }; Option<bool> lightModeOption = new("--light-mode") { Description = "Background color of text displayed on the console: default is black, light mode is white." };
루트 명령을 만드는 줄 뒤 옵션을 추가하는
--file
코드를 삭제합니다. 새 하위 명령에 추가하므로 여기에서 제거합니다.루트 명령을 만드는 줄 뒤
read
하위 명령을 만듭니다. 속성 대신Options
컬렉션 이니셜라이저 구문을 사용하여 이 하위 명령에 옵션을 추가하고 루트 명령에 하위 명령을 추가합니다.Command readCommand = new("read", "Read and display the file.") { fileOption, delayOption, fgcolorOption, lightModeOption }; rootCommand.Subcommands.Add(readCommand);
SetAction
코드를 새 하위 명령에 대한 다음SetAction
코드로 바꿉다.readCommand.SetAction(parseResult => ReadFile( parseResult.GetValue(fileOption), parseResult.GetValue(delayOption), parseResult.GetValue(fgcolorOption), parseResult.GetValue(lightModeOption)));
루트 명령에 더 이상 작업이 필요하지 않으므로 더 이상 루트 명령을 호출
SetAction
하지 않습니다. 명령에 하위 명령이 있는 경우 일반적으로 명령줄 앱을 호출할 때 하위 명령 중 하나를 지정해야 합니다.작업 메서드를
ReadFile
다음 코드로 바꿉다.internal static void ReadFile(FileInfo file, int delay, ConsoleColor fgColor, bool lightMode) { Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black; Console.ForegroundColor = fgColor; foreach (string line in File.ReadLines(file.FullName)) { Console.WriteLine(line); Thread.Sleep(TimeSpan.FromMilliseconds(delay * line.Length)); } }
이제 앱은 다음과 같이 표시됩니다.
using System.CommandLine;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "The file to read and display on the console."
};
Option<int> delayOption = new("--delay")
{
Description = "Delay between lines, specified as milliseconds per character in a line.",
DefaultValueFactory = parseResult => 42
};
Option<ConsoleColor> fgcolorOption = new("--fgcolor")
{
Description = "Foreground color of text displayed on the console.",
DefaultValueFactory = parseResult => ConsoleColor.White
};
Option<bool> lightModeOption = new("--light-mode")
{
Description = "Background color of text displayed on the console: default is black, light mode is white."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
Command readCommand = new("read", "Read and display the file.")
{
fileOption,
delayOption,
fgcolorOption,
lightModeOption
};
rootCommand.Subcommands.Add(readCommand);
readCommand.SetAction(parseResult => ReadFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(delayOption),
parseResult.GetValue(fgcolorOption),
parseResult.GetValue(lightModeOption)));
return rootCommand.Parse(args).Invoke();
}
internal static void ReadFile(FileInfo file, int delay, ConsoleColor fgColor, bool lightMode)
{
Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = fgColor;
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
Thread.Sleep(TimeSpan.FromMilliseconds(delay * line.Length));
}
}
}
새 하위 명령 테스트
이제 하위 명령을 지정하지 않고 앱을 실행하려고 하면 오류 메시지와 사용 가능한 하위 명령을 지정하는 도움말 메시지가 표시됩니다.
scl --file sampleQuotes.txt
'--file' was not matched. Did you mean one of the following?
--help
Required command was not provided.
Unrecognized command or argument '--file'.
Unrecognized command or argument 'sampleQuotes.txt'.
Description:
Sample app for System.CommandLine
Usage:
scl [command] [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
Commands:
read Read and display the file.
하위 명령 read
대한 도움말 텍스트는 네 가지 옵션을 사용할 수 있음을 보여줍니다. 열거형에 유효한 값을 표시합니다.
scl read -h
Description:
Read and display the file.
Usage:
scl read [options]
Options:
--file <file> The file to read and display on the console.
--delay <delay> Delay between lines, specified as milliseconds per
character in a line. [default: 42]
--fgcolor Foreground color of text displayed on the console.
<Black|Blue|Cyan|DarkBlue|DarkCyan|DarkGray|DarkGreen|Dark [default: White]
Magenta|DarkRed|DarkYellow|Gray|Green|Magenta|Red|White|Ye
llow>
--light-mode Background color of text displayed on the console:
default is black, light mode is white.
-?, -h, --help Show help and usage information
read
옵션만 지정하는 하위 명령 --file
실행하고 다른 세 가지 옵션에 대한 기본값을 가져옵니다.
scl read --file sampleQuotes.txt
문자당 42밀리초의 기본 지연으로 인해 읽기 속도가 느려집니다.
--delay
낮은 숫자로 설정하여 속도를 높일 수 있습니다.
scl read --file sampleQuotes.txt --delay 0
--fgcolor
및 --light-mode
사용하여 텍스트 색을 설정할 수 있습니다.
scl read --file sampleQuotes.txt --fgcolor red --light-mode
--delay
잘못된 값을 입력하면 오류 메시지가 표시됩니다.
scl read --file sampleQuotes.txt --delay forty-two
Cannot parse argument 'forty-two' for option '--int' as expected type 'System.Int32'.
--file
잘못된 값을 입력하면 예외가 발생합니다.
scl read --file nofile
Unhandled exception: System.IO.FileNotFoundException: Could not find file 'C:\bin\Debug\net9.0\nofile''.
File name: 'C:\bin\Debug\net9.0\nofile''
하위 명령 및 사용자 지정 유효성 검사 추가
이 섹션에서는 앱의 최종 버전을 만듭니다. 완료되면 앱에는 다음과 같은 명령과 옵션이 있습니다.
- 명명된 recursive* 옵션이 있는 루트 명령
--file
-
quotes
명령-
read
,--delay
및--fgcolor
옵션이 있는--light-mode
명령 -
add
및quote
라고 이름이 붙은 인수가 있는byline
명령 - 이름이
delete
옵션이 있는--search-terms
명령
-
-
* 재귀 옵션은 할당된 명령에 사용할 수 있으며 모든 하위 명령에 재귀적으로 사용할 수 있습니다.
다음은 옵션 및 인수를 사용하여 사용 가능한 각 명령을 호출하는 샘플 명령줄 입력입니다.
scl quotes read --file sampleQuotes.txt --delay 40 --fgcolor red --light-mode
scl quotes add "Hello world!" "Nancy Davolio"
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
Program.cs
--file
옵션을 만드는 코드를 다음 코드로 바꿉니다.Option<FileInfo> fileOption = new("--file") { Description = "An option whose argument is parsed as a FileInfo", Required = true, DefaultValueFactory = result => { if (result.Tokens.Count == 0) { return new FileInfo("sampleQuotes.txt"); } string filePath = result.Tokens.Single().Value; if (!File.Exists(filePath)) { result.AddError("File does not exist"); return null; } else { return new FileInfo(filePath); } } };
이 코드는
System.CommandLine.Parsing.ArgumentResult
사용하여 사용자 지정 구문 분석, 유효성 검사 및 오류 처리를 제공합니다.이 코드가 없으면 누락된 파일이 예외 및 스택 추적으로 보고됩니다. 이 코드를 사용하면 지정된 오류 메시지만 표시됩니다.
또한 이 코드는 기본값을 지정하므로 사용자 지정 구문 분석 메서드로 설정합니다
DefaultValueFactory
.lightModeOption
만드는 코드 후에는add
및delete
명령에 대한 옵션과 인수를 추가합니다.Option<string[]> searchTermsOption = new("--search-terms") { Description = "Strings to search for when deleting entries.", Required = true, AllowMultipleArgumentsPerToken = true }; Argument<string> quoteArgument = new("quote") { Description = "Text of quote." }; Argument<string> bylineArgument = new("byline") { Description = "Byline of quote." };
xref:System.CommandLine.Option.AllowMultipleArgumentsPerToken
설정을 사용하면 첫 번째 항목 뒤의 목록에서 요소를 지정할 때--search-terms
옵션 이름을 생략할 수 있습니다. 명령줄 입력에 해당하는 다음 예제를 만듭니다.scl quotes delete --search-terms David "You can do" scl quotes delete --search-terms David --search-terms "You can do"
루트 명령과
read
명령을 만드는 코드를 다음 코드로 바꿉다.RootCommand rootCommand = new("Sample app for System.CommandLine"); fileOption.Recursive = true; rootCommand.Options.Add(fileOption); Command quotesCommand = new("quotes", "Work with a file that contains quotes."); rootCommand.Subcommands.Add(quotesCommand); Command readCommand = new("read", "Read and display the file.") { delayOption, fgcolorOption, lightModeOption }; quotesCommand.Subcommands.Add(readCommand); Command deleteCommand = new("delete", "Delete lines from the file."); deleteCommand.Options.Add(searchTermsOption); quotesCommand.Subcommands.Add(deleteCommand); Command addCommand = new("add", "Add an entry to the file."); addCommand.Arguments.Add(quoteArgument); addCommand.Arguments.Add(bylineArgument); addCommand.Aliases.Add("insert"); quotesCommand.Subcommands.Add(addCommand);
이 코드는 다음과 같이 변경합니다.
--file
명령에서read
옵션을 제거합니다.--file
루트 명령에 이 옵션을 재귀 옵션으로 추가합니다.quotes
명령을 만들고 루트 명령에 추가합니다.루트 명령 대신
read
명령을quotes
명령에 추가합니다.add
및delete
명령을 만들고quotes
명령에 추가합니다.
결과는 다음 명령 계층 구조입니다.
- 루트 명령
quotes
read
add
delete
이제 앱은 부모 명령()이 영역 또는 그룹을 지정하고 자식 명령(
quotes
,read
,add
)이 작업인delete
패턴을 구현합니다.재귀 옵션은 명령에 적용되고 하위 명령에 재귀적으로 적용됩니다.
--file
루트 명령에 있으므로 앱의 모든 하위 명령에서 자동으로 사용할 수 있습니다.SetAction
코드 후에 새 하위 명령에 대한 새SetAction
코드를 추가합니다.deleteCommand.SetAction(parseResult => DeleteFromFile( parseResult.GetValue(fileOption), parseResult.GetValue(searchTermsOption))); addCommand.SetAction(parseResult => AddToFile( parseResult.GetValue(fileOption), parseResult.GetValue(quoteArgument), parseResult.GetValue(bylineArgument)) );
하위 명령은
quotes
리프 명령이 아니므로 작업이 없습니다. 하위 명령read
,add
및delete
quotes
아래의 리프 명령이며 각각에 대해SetAction
호출됩니다.add
및delete
에 대한 작업을 추가합니다.internal static void DeleteFromFile(FileInfo file, string[] searchTerms) { Console.WriteLine("Deleting from file"); var lines = File.ReadLines(file.FullName).Where(line => searchTerms.All(s => !line.Contains(s))); File.WriteAllLines(file.FullName, lines); } internal static void AddToFile(FileInfo file, string quote, string byline) { Console.WriteLine("Adding to file"); using StreamWriter writer = file.AppendText(); writer.WriteLine($"{Environment.NewLine}{Environment.NewLine}{quote}"); writer.WriteLine($"{Environment.NewLine}-{byline}"); }
완성된 앱은 다음과 같습니다.
using System.CommandLine;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "An option whose argument is parsed as a FileInfo",
Required = true,
DefaultValueFactory = result =>
{
if (result.Tokens.Count == 0)
{
return new FileInfo("sampleQuotes.txt");
}
string filePath = result.Tokens.Single().Value;
if (!File.Exists(filePath))
{
result.AddError("File does not exist");
return null;
}
else
{
return new FileInfo(filePath);
}
}
};
Option<int> delayOption = new("--delay")
{
Description = "Delay between lines, specified as milliseconds per character in a line.",
DefaultValueFactory = parseResult => 42
};
Option<ConsoleColor> fgcolorOption = new("--fgcolor")
{
Description = "Foreground color of text displayed on the console.",
DefaultValueFactory = parseResult => ConsoleColor.White
};
Option<bool> lightModeOption = new("--light-mode")
{
Description = "Background color of text displayed on the console: default is black, light mode is white."
};
Option<string[]> searchTermsOption = new("--search-terms")
{
Description = "Strings to search for when deleting entries.",
Required = true,
AllowMultipleArgumentsPerToken = true
};
Argument<string> quoteArgument = new("quote")
{
Description = "Text of quote."
};
Argument<string> bylineArgument = new("byline")
{
Description = "Byline of quote."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
fileOption.Recursive = true;
rootCommand.Options.Add(fileOption);
Command quotesCommand = new("quotes", "Work with a file that contains quotes.");
rootCommand.Subcommands.Add(quotesCommand);
Command readCommand = new("read", "Read and display the file.")
{
delayOption,
fgcolorOption,
lightModeOption
};
quotesCommand.Subcommands.Add(readCommand);
Command deleteCommand = new("delete", "Delete lines from the file.");
deleteCommand.Options.Add(searchTermsOption);
quotesCommand.Subcommands.Add(deleteCommand);
Command addCommand = new("add", "Add an entry to the file.");
addCommand.Arguments.Add(quoteArgument);
addCommand.Arguments.Add(bylineArgument);
addCommand.Aliases.Add("insert");
quotesCommand.Subcommands.Add(addCommand);
readCommand.SetAction(parseResult => ReadFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(delayOption),
parseResult.GetValue(fgcolorOption),
parseResult.GetValue(lightModeOption)));
deleteCommand.SetAction(parseResult => DeleteFromFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(searchTermsOption)));
addCommand.SetAction(parseResult => AddToFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(quoteArgument),
parseResult.GetValue(bylineArgument))
);
return rootCommand.Parse(args).Invoke();
}
internal static void ReadFile(FileInfo file, int delay, ConsoleColor fgColor, bool lightMode)
{
Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = fgColor;
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
Thread.Sleep(TimeSpan.FromMilliseconds(delay * line.Length));
}
}
internal static void DeleteFromFile(FileInfo file, string[] searchTerms)
{
Console.WriteLine("Deleting from file");
var lines = File.ReadLines(file.FullName).Where(line => searchTerms.All(s => !line.Contains(s)));
File.WriteAllLines(file.FullName, lines);
}
internal static void AddToFile(FileInfo file, string quote, string byline)
{
Console.WriteLine("Adding to file");
using StreamWriter writer = file.AppendText();
writer.WriteLine($"{Environment.NewLine}{Environment.NewLine}{quote}");
writer.WriteLine($"{Environment.NewLine}-{byline}");
}
}
프로젝트를 빌드한 다음, 다음 명령을 시도합니다.
존재하지 않는 파일을 --file
명령을 사용하여 read
제출하면 예외 및 스택 추적 대신 오류 메시지가 표시됩니다.
scl quotes read --file nofile
File does not exist
하위 명령 quotes
실행하면 read
, add
또는 delete
사용하도록 지시하는 메시지가 표시됩니다.
scl quotes
Required command was not provided.
Description:
Work with a file that contains quotes.
Usage:
scl quotes [command] [options]
Options:
--file <file> An option whose argument is parsed as a FileInfo [default: sampleQuotes.txt]
-?, -h, --help Show help and usage information
Commands:
read Read and display the file.
delete Delete lines from the file.
add, insert <quote> <byline> Add an entry to the file.
하위 명령 add
실행한 다음 텍스트 파일의 끝을 확인하여 추가된 텍스트를 확인합니다.
scl quotes add "Hello world!" "Nancy Davolio"
파일의 시작 부분에서 검색 문자열을 사용하여 하위 명령 delete
실행한 다음 텍스트 파일의 시작을 확인하여 텍스트가 제거된 위치를 확인합니다.
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
비고
bin/debug/net9.0 폴더에서 실행하고 있다면, 해당 폴더에서 add
및 delete
명령어를 통해 변경된 파일을 찾을 수 있습니다. 프로젝트 폴더에 있는 파일의 복사본은 변경되지 않은 상태로 유지됩니다.
다음 단계
이 자습서에서는 System.CommandLine
사용하는 간단한 명령줄 앱을 만들었습니다. 라이브러리에 대한 자세한 내용은 System.CommandLine 개요참조하세요.
.NET